<template><h1 id="注册、登录和鉴权" tabindex="-1"><a class="header-anchor" href="#注册、登录和鉴权" aria-hidden="true">#</a> 注册、登录和鉴权</h1>
<h2 id="简介" tabindex="-1"><a class="header-anchor" href="#简介" aria-hidden="true">#</a> 简介</h2>
<p>​	本文主要实现注册、登录和鉴权，其中包括注册码的获取，注册码请求次数的限定，注册完成后使用BCrypt对密码加密存储，使用token进行登录认证，JWT生成，登录成功获取JWT，访问接口通过JWT进行鉴权。</p>
<h2 id="引入包" tabindex="-1"><a class="header-anchor" href="#引入包" aria-hidden="true">#</a> 引入包</h2>
<div class="language-text ext-text line-numbers-mode"><pre v-pre class="language-text"><code>implementation 'org.springframework.boot:spring-boot-starter-validation'
    implementation('org.springframework.boot:spring-boot-starter-data-redis')
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-aop'
    implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.10.7'
    implementation group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.10.7'
    implementation group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.10.7'
    implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.11'
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><h2 id="封装resultvo实现统一返回结果" tabindex="-1"><a class="header-anchor" href="#封装resultvo实现统一返回结果" aria-hidden="true">#</a> 封装ResultVO实现统一返回结果</h2>
<p>通过RestFul接口开发的接口，一般含有接口执行状态（访问的成功失败状态码、失败描述、成功的数据返回对象）,包括方便构造ResultVO的success、error方法函数。返回的结果样式如下:</p>
<div class="language-json ext-json line-numbers-mode"><pre v-pre class="language-json"><code><span class="token punctuation">{</span>
  <span class="token property">"code"</span><span class="token operator">:</span> <span class="token number">2000</span><span class="token punctuation">,</span>
  <span class="token property">"msg"</span><span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">,</span>
  <span class="token property">"data"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><div class="language-java ext-java line-numbers-mode"><pre v-pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">cn<span class="token punctuation">.</span>makerknz<span class="token punctuation">.</span>product<span class="token punctuation">.</span>server<span class="token punctuation">.</span>domain<span class="token punctuation">.</span>vo</span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token namespace">cn<span class="token punctuation">.</span>makerknz<span class="token punctuation">.</span>product<span class="token punctuation">.</span>server<span class="token punctuation">.</span>domain<span class="token punctuation">.</span>enums<span class="token punctuation">.</span></span><span class="token class-name">ResponseEnum</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">com<span class="token punctuation">.</span>fasterxml<span class="token punctuation">.</span>jackson<span class="token punctuation">.</span>annotation<span class="token punctuation">.</span></span><span class="token class-name">JsonInclude</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">lombok<span class="token punctuation">.</span></span><span class="token class-name">Data</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>validation<span class="token punctuation">.</span></span><span class="token class-name">BindingResult</span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">Objects</span><span class="token punctuation">;</span>

<span class="token doc-comment comment">/**
 * @Author: maker_knz
 * @Date: 2021/4/19/019 14:30
 * @Version 1.0
 */</span>

<span class="token annotation punctuation">@Data</span>
<span class="token annotation punctuation">@JsonInclude</span><span class="token punctuation">(</span>value <span class="token operator">=</span> <span class="token class-name">JsonInclude<span class="token punctuation">.</span>Include</span><span class="token punctuation">.</span>NON_NULL<span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ResultVO</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">></span></span> <span class="token punctuation">{</span>

    <span class="token doc-comment comment">/**
     * 状态码
     */</span>
    <span class="token keyword">private</span> <span class="token class-name">Integer</span> code<span class="token punctuation">;</span>

    <span class="token doc-comment comment">/**
     * 描述
     */</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> msg<span class="token punctuation">;</span>

    <span class="token doc-comment comment">/**
     * 数据
     */</span>
    <span class="token keyword">private</span> <span class="token class-name">T</span> data<span class="token punctuation">;</span>

    <span class="token doc-comment comment">/**
     * 构造函数
     * <span class="token keyword">@param</span> <span class="token parameter">code</span>
     * <span class="token keyword">@param</span> <span class="token parameter">msg</span>
     */</span>
    <span class="token keyword">public</span> <span class="token class-name">ResultVO</span><span class="token punctuation">(</span><span class="token class-name">Integer</span> code<span class="token punctuation">,</span> <span class="token class-name">String</span> msg<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>code <span class="token operator">=</span> code<span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>msg <span class="token operator">=</span> msg<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    
    <span class="token keyword">public</span> <span class="token class-name">ResultVO</span><span class="token punctuation">(</span><span class="token class-name">Integer</span> code<span class="token punctuation">,</span> <span class="token class-name">String</span> msg<span class="token punctuation">,</span> <span class="token class-name">T</span> data<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>code <span class="token operator">=</span> code<span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>msg <span class="token operator">=</span> msg<span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>data <span class="token operator">=</span> data<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">private</span> <span class="token class-name">ResultVO</span><span class="token punctuation">(</span><span class="token class-name">Integer</span> code<span class="token punctuation">,</span> <span class="token class-name">T</span> data<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>code <span class="token operator">=</span> code<span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>data <span class="token operator">=</span> data<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token doc-comment comment">/**
     * 成功返回
     * <span class="token keyword">@param</span> <span class="token parameter">msg</span>
     * <span class="token keyword">@param</span> <span class="token class-name"><span class="token punctuation">&lt;</span>T<span class="token punctuation">></span></span>
     * <span class="token keyword">@return</span>
     */</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">></span></span> <span class="token class-name">ResultVO</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">></span></span> <span class="token function">successMsg</span><span class="token punctuation">(</span><span class="token class-name">String</span> msg<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">ResultVO</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token class-name">ResponseEnum</span><span class="token punctuation">.</span>SUCCESS<span class="token punctuation">.</span><span class="token function">getCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> msg<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">></span></span> <span class="token class-name">ResultVO</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">></span></span> <span class="token function">success</span><span class="token punctuation">(</span><span class="token class-name">T</span> data<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">ResultVO</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token class-name">ResponseEnum</span><span class="token punctuation">.</span>SUCCESS<span class="token punctuation">.</span><span class="token function">getCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> data<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">></span></span> <span class="token class-name">ResultVO</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">></span></span> <span class="token function">success</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">ResultVO</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token class-name">ResponseEnum</span><span class="token punctuation">.</span>SUCCESS<span class="token punctuation">.</span><span class="token function">getCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">ResponseEnum</span><span class="token punctuation">.</span>SUCCESS<span class="token punctuation">.</span><span class="token function">getDesc</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">></span></span> <span class="token class-name">ResultVO</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">></span></span> <span class="token function">error</span><span class="token punctuation">(</span><span class="token class-name">ResponseEnum</span> responseEnum<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">ResultVO</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token punctuation">></span></span><span class="token punctuation">(</span>responseEnum<span class="token punctuation">.</span><span class="token function">getCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> responseEnum<span class="token punctuation">.</span><span class="token function">getDesc</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">></span></span> <span class="token class-name">ResultVO</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">></span></span> <span class="token function">error</span><span class="token punctuation">(</span><span class="token class-name">ResponseEnum</span> responseEnum<span class="token punctuation">,</span> <span class="token class-name">String</span> msg<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">ResultVO</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token punctuation">></span></span><span class="token punctuation">(</span>responseEnum<span class="token punctuation">.</span><span class="token function">getCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> msg<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">></span></span> <span class="token class-name">ResultVO</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">></span></span> <span class="token function">error</span><span class="token punctuation">(</span><span class="token class-name">ResponseEnum</span> responseEnum<span class="token punctuation">,</span> <span class="token class-name">BindingResult</span> bindingResult<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">ResultVO</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token punctuation">></span></span><span class="token punctuation">(</span>responseEnum<span class="token punctuation">.</span><span class="token function">getCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
                <span class="token class-name">Objects</span><span class="token punctuation">.</span><span class="token function">requireNonNull</span><span class="token punctuation">(</span>bindingResult<span class="token punctuation">.</span><span class="token function">getFieldError</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getField</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token string">" "</span> <span class="token operator">+</span> bindingResult<span class="token punctuation">.</span><span class="token function">getFieldError</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getDefaultMessage</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br></div></div><p>为了方便查找错误在这里定义了ResponseEnum枚举类，针对每个错误提供一个错误码。</p>
<div class="language-java ext-java line-numbers-mode"><pre v-pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">cn<span class="token punctuation">.</span>makerknz<span class="token punctuation">.</span>product<span class="token punctuation">.</span>server<span class="token punctuation">.</span>domain<span class="token punctuation">.</span>enums</span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token namespace">lombok<span class="token punctuation">.</span></span><span class="token class-name">Getter</span><span class="token punctuation">;</span>

<span class="token doc-comment comment">/**
 * @Author: maker_knz
 * @Date: 2021/4/19/019 14:32
 * @Version 1.0
 */</span>

<span class="token annotation punctuation">@Getter</span>
<span class="token keyword">public</span> <span class="token keyword">enum</span> <span class="token class-name">ResponseEnum</span> <span class="token punctuation">{</span>
    <span class="token function">ERROR</span><span class="token punctuation">(</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token string">"服务端错误"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>

    <span class="token function">SUCCESS</span><span class="token punctuation">(</span><span class="token number">2000</span><span class="token punctuation">,</span> <span class="token string">"成功"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>

    <span class="token function">ADD_USER_ERROR</span><span class="token punctuation">(</span><span class="token number">10001</span><span class="token punctuation">,</span> <span class="token string">"创建用户错误"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>

    <span class="token function">UPDATE_USER_ERROR</span><span class="token punctuation">(</span><span class="token number">10002</span><span class="token punctuation">,</span> <span class="token string">"更新用户错误"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>

    <span class="token function">WECHAT_LOGIN_ERROR</span><span class="token punctuation">(</span><span class="token number">1008</span><span class="token punctuation">,</span> <span class="token string">"校验失败"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>

    <span class="token function">TOKEN_ERROR</span><span class="token punctuation">(</span><span class="token number">1009</span><span class="token punctuation">,</span> <span class="token string">"token无效"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token punctuation">;</span>

    <span class="token class-name">Integer</span> code<span class="token punctuation">;</span>

    <span class="token class-name">String</span> desc<span class="token punctuation">;</span>

    <span class="token class-name">ResponseEnum</span><span class="token punctuation">(</span><span class="token class-name">Integer</span> code<span class="token punctuation">,</span> <span class="token class-name">String</span> desc<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>code <span class="token operator">=</span> code<span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>desc <span class="token operator">=</span> desc<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br></div></div><h2 id="加密" tabindex="-1"><a class="header-anchor" href="#加密" aria-hidden="true">#</a> 加密</h2>
<p>使用<a href="https://www.jianshu.com/p/2b131bfc2f10" target="_blank" rel="noopener noreferrer">BCrypt<ExternalLinkIcon/></a></p>
<p>加密</p>
<p>BCrypt.hashpw(password, BCrypt.gensalt())</p>
<p>解密</p>
<p>BCrypt.checkpw(candidatePassword, dbPassword)</p>
<p>此处代码直接从spring security中拷贝出来</p>
<div class="language-java ext-java line-numbers-mode"><pre v-pre class="language-java"><code><span class="token comment">// Copyright (c) 2006 Damien Miller &lt;djm@mindrot.org></span>
<span class="token comment">//</span>
<span class="token comment">// Permission to use, copy, modify, and distribute this software for any</span>
<span class="token comment">// purpose with or without fee is hereby granted, provided that the above</span>
<span class="token comment">// copyright notice and this permission notice appear in all copies.</span>
<span class="token comment">//</span>
<span class="token comment">// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES</span>
<span class="token comment">// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF</span>
<span class="token comment">// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR</span>
<span class="token comment">// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES</span>
<span class="token comment">// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN</span>
<span class="token comment">// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF</span>
<span class="token comment">// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.</span>

<span class="token keyword">package</span> <span class="token namespace">cn<span class="token punctuation">.</span>makerknz<span class="token punctuation">.</span>product<span class="token punctuation">.</span>server<span class="token punctuation">.</span>utils</span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token namespace">java<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span><span class="token class-name">UnsupportedEncodingException</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">java<span class="token punctuation">.</span>security<span class="token punctuation">.</span></span><span class="token class-name">SecureRandom</span><span class="token punctuation">;</span>

<span class="token doc-comment comment">/**
 * BCrypt implements OpenBSD-style Blowfish password hashing using
 * the scheme described in "A Future-Adaptable Password Scheme" by
 * Niels Provos and David Mazieres.
 * <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>
 * This password hashing system tries to thwart off-line password
 * cracking using a computationally-intensive hashing algorithm,
 * based on Bruce Schneier's Blowfish cipher. The work factor of
 * the algorithm is parameterised, so it can be increased as
 * computers get faster.
 * <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>
 * Usage is really simple. To hash a password for the first time,
 * call the hashpw method with a random salt, like this:
 * <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>
 * <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>code</span><span class="token punctuation">></span></span>
 <span class="token code-section">* <span class="token line"><span class="token code language-java"><span class="token class-name">String</span> pw_hash <span class="token operator">=</span> <span class="token class-name">BCrypt</span><span class="token punctuation">.</span><span class="token function">hashpw</span><span class="token punctuation">(</span>plain_password<span class="token punctuation">,</span> <span class="token class-name">BCrypt</span><span class="token punctuation">.</span><span class="token function">gensalt</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>br</span> <span class="token punctuation">/></span></span></span>
 *</span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>code</span><span class="token punctuation">></span></span>
 * <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>
 * To check whether a plaintext password matches one that has been
 * hashed previously, use the checkpw method:
 * <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>
 * <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>code</span><span class="token punctuation">></span></span>
 <span class="token code-section">* <span class="token line"><span class="token code language-java"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name">BCrypt</span><span class="token punctuation">.</span><span class="token function">checkpw</span><span class="token punctuation">(</span>candidate_password<span class="token punctuation">,</span> stored_hash<span class="token punctuation">)</span><span class="token punctuation">)</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>br</span> <span class="token punctuation">/></span></span></span>
 * <span class="token line"><span class="token entity named-entity" title="&nbsp;">&amp;nbsp;</span><span class="token entity named-entity" title="&nbsp;">&amp;nbsp;</span><span class="token entity named-entity" title="&nbsp;">&amp;nbsp;</span><span class="token entity named-entity" title="&nbsp;">&amp;nbsp;</span><span class="token code language-java"><span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"It matches"</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>br</span> <span class="token punctuation">/></span></span></span>
 * <span class="token line"><span class="token code language-java"><span class="token keyword">else</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>br</span> <span class="token punctuation">/></span></span></span>
 * <span class="token line"><span class="token entity named-entity" title="&nbsp;">&amp;nbsp;</span><span class="token entity named-entity" title="&nbsp;">&amp;nbsp;</span><span class="token entity named-entity" title="&nbsp;">&amp;nbsp;</span><span class="token entity named-entity" title="&nbsp;">&amp;nbsp;</span><span class="token code language-java"><span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"It does not match"</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>br</span> <span class="token punctuation">/></span></span></span>
 *</span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>code</span><span class="token punctuation">></span></span>
 * <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>
 * The gensalt() method takes an optional parameter (log_rounds)
 * that determines the computational complexity of the hashing:
 * <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>
 * <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>code</span><span class="token punctuation">></span></span>
 <span class="token code-section">* <span class="token line"><span class="token code language-java"><span class="token class-name">String</span> strong_salt <span class="token operator">=</span> <span class="token class-name">BCrypt</span><span class="token punctuation">.</span><span class="token function">gensalt</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>br</span> <span class="token punctuation">/></span></span></span>
 * <span class="token line"><span class="token code language-java"><span class="token class-name">String</span> stronger_salt <span class="token operator">=</span> <span class="token class-name">BCrypt</span><span class="token punctuation">.</span><span class="token function">gensalt</span><span class="token punctuation">(</span><span class="token number">12</span><span class="token punctuation">)</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>br</span> <span class="token punctuation">/></span></span></span>
 *</span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>code</span><span class="token punctuation">></span></span>
 * <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>
 * The amount of work increases exponentially (2**log_rounds), so 
 * each increment is twice as much work. The default log_rounds is
 * 10, and the valid range is 4 to 30.
 *
 * <span class="token keyword">@author</span> Damien Miller
 * <span class="token keyword">@version</span> 0.2
 */</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">BCrypt</span> <span class="token punctuation">{</span>
	<span class="token comment">// BCrypt parameters</span>
	<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">int</span> GENSALT_DEFAULT_LOG2_ROUNDS <span class="token operator">=</span> <span class="token number">10</span><span class="token punctuation">;</span>
	<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">int</span> BCRYPT_SALT_LEN <span class="token operator">=</span> <span class="token number">16</span><span class="token punctuation">;</span>

	<span class="token comment">// Blowfish parameters</span>
	<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">int</span> BLOWFISH_NUM_ROUNDS <span class="token operator">=</span> <span class="token number">16</span><span class="token punctuation">;</span>

	<span class="token comment">// Initial contents of key schedule</span>
	<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">int</span> <span class="token class-name">P_orig</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
		<span class="token number">0x243f6a88</span><span class="token punctuation">,</span> <span class="token number">0x85a308d3</span><span class="token punctuation">,</span> <span class="token number">0x13198a2e</span><span class="token punctuation">,</span> <span class="token number">0x03707344</span><span class="token punctuation">,</span>
		<span class="token number">0xa4093822</span><span class="token punctuation">,</span> <span class="token number">0x299f31d0</span><span class="token punctuation">,</span> <span class="token number">0x082efa98</span><span class="token punctuation">,</span> <span class="token number">0xec4e6c89</span><span class="token punctuation">,</span>
		<span class="token number">0x452821e6</span><span class="token punctuation">,</span> <span class="token number">0x38d01377</span><span class="token punctuation">,</span> <span class="token number">0xbe5466cf</span><span class="token punctuation">,</span> <span class="token number">0x34e90c6c</span><span class="token punctuation">,</span>
		<span class="token number">0xc0ac29b7</span><span class="token punctuation">,</span> <span class="token number">0xc97c50dd</span><span class="token punctuation">,</span> <span class="token number">0x3f84d5b5</span><span class="token punctuation">,</span> <span class="token number">0xb5470917</span><span class="token punctuation">,</span>
		<span class="token number">0x9216d5d9</span><span class="token punctuation">,</span> <span class="token number">0x8979fb1b</span>
	<span class="token punctuation">}</span><span class="token punctuation">;</span>
	<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">int</span> <span class="token class-name">S_orig</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
		<span class="token number">0xd1310ba6</span><span class="token punctuation">,</span> <span class="token number">0x98dfb5ac</span><span class="token punctuation">,</span> <span class="token number">0x2ffd72db</span><span class="token punctuation">,</span> <span class="token number">0xd01adfb7</span><span class="token punctuation">,</span>
		<span class="token number">0xb8e1afed</span><span class="token punctuation">,</span> <span class="token number">0x6a267e96</span><span class="token punctuation">,</span> <span class="token number">0xba7c9045</span><span class="token punctuation">,</span> <span class="token number">0xf12c7f99</span><span class="token punctuation">,</span>
		<span class="token number">0x24a19947</span><span class="token punctuation">,</span> <span class="token number">0xb3916cf7</span><span class="token punctuation">,</span> <span class="token number">0x0801f2e2</span><span class="token punctuation">,</span> <span class="token number">0x858efc16</span><span class="token punctuation">,</span>
		<span class="token number">0x636920d8</span><span class="token punctuation">,</span> <span class="token number">0x71574e69</span><span class="token punctuation">,</span> <span class="token number">0xa458fea3</span><span class="token punctuation">,</span> <span class="token number">0xf4933d7e</span><span class="token punctuation">,</span>
		<span class="token number">0x0d95748f</span><span class="token punctuation">,</span> <span class="token number">0x728eb658</span><span class="token punctuation">,</span> <span class="token number">0x718bcd58</span><span class="token punctuation">,</span> <span class="token number">0x82154aee</span><span class="token punctuation">,</span>
		<span class="token number">0x7b54a41d</span><span class="token punctuation">,</span> <span class="token number">0xc25a59b5</span><span class="token punctuation">,</span> <span class="token number">0x9c30d539</span><span class="token punctuation">,</span> <span class="token number">0x2af26013</span><span class="token punctuation">,</span>
		<span class="token number">0xc5d1b023</span><span class="token punctuation">,</span> <span class="token number">0x286085f0</span><span class="token punctuation">,</span> <span class="token number">0xca417918</span><span class="token punctuation">,</span> <span class="token number">0xb8db38ef</span><span class="token punctuation">,</span>
		<span class="token number">0x8e79dcb0</span><span class="token punctuation">,</span> <span class="token number">0x603a180e</span><span class="token punctuation">,</span> <span class="token number">0x6c9e0e8b</span><span class="token punctuation">,</span> <span class="token number">0xb01e8a3e</span><span class="token punctuation">,</span>
		<span class="token number">0xd71577c1</span><span class="token punctuation">,</span> <span class="token number">0xbd314b27</span><span class="token punctuation">,</span> <span class="token number">0x78af2fda</span><span class="token punctuation">,</span> <span class="token number">0x55605c60</span><span class="token punctuation">,</span>
		<span class="token number">0xe65525f3</span><span class="token punctuation">,</span> <span class="token number">0xaa55ab94</span><span class="token punctuation">,</span> <span class="token number">0x57489862</span><span class="token punctuation">,</span> <span class="token number">0x63e81440</span><span class="token punctuation">,</span>
		<span class="token number">0x55ca396a</span><span class="token punctuation">,</span> <span class="token number">0x2aab10b6</span><span class="token punctuation">,</span> <span class="token number">0xb4cc5c34</span><span class="token punctuation">,</span> <span class="token number">0x1141e8ce</span><span class="token punctuation">,</span>
		<span class="token number">0xa15486af</span><span class="token punctuation">,</span> <span class="token number">0x7c72e993</span><span class="token punctuation">,</span> <span class="token number">0xb3ee1411</span><span class="token punctuation">,</span> <span class="token number">0x636fbc2a</span><span class="token punctuation">,</span>
		<span class="token number">0x2ba9c55d</span><span class="token punctuation">,</span> <span class="token number">0x741831f6</span><span class="token punctuation">,</span> <span class="token number">0xce5c3e16</span><span class="token punctuation">,</span> <span class="token number">0x9b87931e</span><span class="token punctuation">,</span>
		<span class="token number">0xafd6ba33</span><span class="token punctuation">,</span> <span class="token number">0x6c24cf5c</span><span class="token punctuation">,</span> <span class="token number">0x7a325381</span><span class="token punctuation">,</span> <span class="token number">0x28958677</span><span class="token punctuation">,</span>
		<span class="token number">0x3b8f4898</span><span class="token punctuation">,</span> <span class="token number">0x6b4bb9af</span><span class="token punctuation">,</span> <span class="token number">0xc4bfe81b</span><span class="token punctuation">,</span> <span class="token number">0x66282193</span><span class="token punctuation">,</span>
		<span class="token number">0x61d809cc</span><span class="token punctuation">,</span> <span class="token number">0xfb21a991</span><span class="token punctuation">,</span> <span class="token number">0x487cac60</span><span class="token punctuation">,</span> <span class="token number">0x5dec8032</span><span class="token punctuation">,</span>
		<span class="token number">0xef845d5d</span><span class="token punctuation">,</span> <span class="token number">0xe98575b1</span><span class="token punctuation">,</span> <span class="token number">0xdc262302</span><span class="token punctuation">,</span> <span class="token number">0xeb651b88</span><span class="token punctuation">,</span>
		<span class="token number">0x23893e81</span><span class="token punctuation">,</span> <span class="token number">0xd396acc5</span><span class="token punctuation">,</span> <span class="token number">0x0f6d6ff3</span><span class="token punctuation">,</span> <span class="token number">0x83f44239</span><span class="token punctuation">,</span>
		<span class="token number">0x2e0b4482</span><span class="token punctuation">,</span> <span class="token number">0xa4842004</span><span class="token punctuation">,</span> <span class="token number">0x69c8f04a</span><span class="token punctuation">,</span> <span class="token number">0x9e1f9b5e</span><span class="token punctuation">,</span>
		<span class="token number">0x21c66842</span><span class="token punctuation">,</span> <span class="token number">0xf6e96c9a</span><span class="token punctuation">,</span> <span class="token number">0x670c9c61</span><span class="token punctuation">,</span> <span class="token number">0xabd388f0</span><span class="token punctuation">,</span>
		<span class="token number">0x6a51a0d2</span><span class="token punctuation">,</span> <span class="token number">0xd8542f68</span><span class="token punctuation">,</span> <span class="token number">0x960fa728</span><span class="token punctuation">,</span> <span class="token number">0xab5133a3</span><span class="token punctuation">,</span>
		<span class="token number">0x6eef0b6c</span><span class="token punctuation">,</span> <span class="token number">0x137a3be4</span><span class="token punctuation">,</span> <span class="token number">0xba3bf050</span><span class="token punctuation">,</span> <span class="token number">0x7efb2a98</span><span class="token punctuation">,</span>
		<span class="token number">0xa1f1651d</span><span class="token punctuation">,</span> <span class="token number">0x39af0176</span><span class="token punctuation">,</span> <span class="token number">0x66ca593e</span><span class="token punctuation">,</span> <span class="token number">0x82430e88</span><span class="token punctuation">,</span>
		<span class="token number">0x8cee8619</span><span class="token punctuation">,</span> <span class="token number">0x456f9fb4</span><span class="token punctuation">,</span> <span class="token number">0x7d84a5c3</span><span class="token punctuation">,</span> <span class="token number">0x3b8b5ebe</span><span class="token punctuation">,</span>
		<span class="token number">0xe06f75d8</span><span class="token punctuation">,</span> <span class="token number">0x85c12073</span><span class="token punctuation">,</span> <span class="token number">0x401a449f</span><span class="token punctuation">,</span> <span class="token number">0x56c16aa6</span><span class="token punctuation">,</span>
		<span class="token number">0x4ed3aa62</span><span class="token punctuation">,</span> <span class="token number">0x363f7706</span><span class="token punctuation">,</span> <span class="token number">0x1bfedf72</span><span class="token punctuation">,</span> <span class="token number">0x429b023d</span><span class="token punctuation">,</span>
		<span class="token number">0x37d0d724</span><span class="token punctuation">,</span> <span class="token number">0xd00a1248</span><span class="token punctuation">,</span> <span class="token number">0xdb0fead3</span><span class="token punctuation">,</span> <span class="token number">0x49f1c09b</span><span class="token punctuation">,</span>
		<span class="token number">0x075372c9</span><span class="token punctuation">,</span> <span class="token number">0x80991b7b</span><span class="token punctuation">,</span> <span class="token number">0x25d479d8</span><span class="token punctuation">,</span> <span class="token number">0xf6e8def7</span><span class="token punctuation">,</span>
		<span class="token number">0xe3fe501a</span><span class="token punctuation">,</span> <span class="token number">0xb6794c3b</span><span class="token punctuation">,</span> <span class="token number">0x976ce0bd</span><span class="token punctuation">,</span> <span class="token number">0x04c006ba</span><span class="token punctuation">,</span>
		<span class="token number">0xc1a94fb6</span><span class="token punctuation">,</span> <span class="token number">0x409f60c4</span><span class="token punctuation">,</span> <span class="token number">0x5e5c9ec2</span><span class="token punctuation">,</span> <span class="token number">0x196a2463</span><span class="token punctuation">,</span>
		<span class="token number">0x68fb6faf</span><span class="token punctuation">,</span> <span class="token number">0x3e6c53b5</span><span class="token punctuation">,</span> <span class="token number">0x1339b2eb</span><span class="token punctuation">,</span> <span class="token number">0x3b52ec6f</span><span class="token punctuation">,</span>
		<span class="token number">0x6dfc511f</span><span class="token punctuation">,</span> <span class="token number">0x9b30952c</span><span class="token punctuation">,</span> <span class="token number">0xcc814544</span><span class="token punctuation">,</span> <span class="token number">0xaf5ebd09</span><span class="token punctuation">,</span>
		<span class="token number">0xbee3d004</span><span class="token punctuation">,</span> <span class="token number">0xde334afd</span><span class="token punctuation">,</span> <span class="token number">0x660f2807</span><span class="token punctuation">,</span> <span class="token number">0x192e4bb3</span><span class="token punctuation">,</span>
		<span class="token number">0xc0cba857</span><span class="token punctuation">,</span> <span class="token number">0x45c8740f</span><span class="token punctuation">,</span> <span class="token number">0xd20b5f39</span><span class="token punctuation">,</span> <span class="token number">0xb9d3fbdb</span><span class="token punctuation">,</span>
		<span class="token number">0x5579c0bd</span><span class="token punctuation">,</span> <span class="token number">0x1a60320a</span><span class="token punctuation">,</span> <span class="token number">0xd6a100c6</span><span class="token punctuation">,</span> <span class="token number">0x402c7279</span><span class="token punctuation">,</span>
		<span class="token number">0x679f25fe</span><span class="token punctuation">,</span> <span class="token number">0xfb1fa3cc</span><span class="token punctuation">,</span> <span class="token number">0x8ea5e9f8</span><span class="token punctuation">,</span> <span class="token number">0xdb3222f8</span><span class="token punctuation">,</span>
		<span class="token number">0x3c7516df</span><span class="token punctuation">,</span> <span class="token number">0xfd616b15</span><span class="token punctuation">,</span> <span class="token number">0x2f501ec8</span><span class="token punctuation">,</span> <span class="token number">0xad0552ab</span><span class="token punctuation">,</span>
		<span class="token number">0x323db5fa</span><span class="token punctuation">,</span> <span class="token number">0xfd238760</span><span class="token punctuation">,</span> <span class="token number">0x53317b48</span><span class="token punctuation">,</span> <span class="token number">0x3e00df82</span><span class="token punctuation">,</span>
		<span class="token number">0x9e5c57bb</span><span class="token punctuation">,</span> <span class="token number">0xca6f8ca0</span><span class="token punctuation">,</span> <span class="token number">0x1a87562e</span><span class="token punctuation">,</span> <span class="token number">0xdf1769db</span><span class="token punctuation">,</span>
		<span class="token number">0xd542a8f6</span><span class="token punctuation">,</span> <span class="token number">0x287effc3</span><span class="token punctuation">,</span> <span class="token number">0xac6732c6</span><span class="token punctuation">,</span> <span class="token number">0x8c4f5573</span><span class="token punctuation">,</span>
		<span class="token number">0x695b27b0</span><span class="token punctuation">,</span> <span class="token number">0xbbca58c8</span><span class="token punctuation">,</span> <span class="token number">0xe1ffa35d</span><span class="token punctuation">,</span> <span class="token number">0xb8f011a0</span><span class="token punctuation">,</span>
		<span class="token number">0x10fa3d98</span><span class="token punctuation">,</span> <span class="token number">0xfd2183b8</span><span class="token punctuation">,</span> <span class="token number">0x4afcb56c</span><span class="token punctuation">,</span> <span class="token number">0x2dd1d35b</span><span class="token punctuation">,</span>
		<span class="token number">0x9a53e479</span><span class="token punctuation">,</span> <span class="token number">0xb6f84565</span><span class="token punctuation">,</span> <span class="token number">0xd28e49bc</span><span class="token punctuation">,</span> <span class="token number">0x4bfb9790</span><span class="token punctuation">,</span>
		<span class="token number">0xe1ddf2da</span><span class="token punctuation">,</span> <span class="token number">0xa4cb7e33</span><span class="token punctuation">,</span> <span class="token number">0x62fb1341</span><span class="token punctuation">,</span> <span class="token number">0xcee4c6e8</span><span class="token punctuation">,</span>
		<span class="token number">0xef20cada</span><span class="token punctuation">,</span> <span class="token number">0x36774c01</span><span class="token punctuation">,</span> <span class="token number">0xd07e9efe</span><span class="token punctuation">,</span> <span class="token number">0x2bf11fb4</span><span class="token punctuation">,</span>
		<span class="token number">0x95dbda4d</span><span class="token punctuation">,</span> <span class="token number">0xae909198</span><span class="token punctuation">,</span> <span class="token number">0xeaad8e71</span><span class="token punctuation">,</span> <span class="token number">0x6b93d5a0</span><span class="token punctuation">,</span>
		<span class="token number">0xd08ed1d0</span><span class="token punctuation">,</span> <span class="token number">0xafc725e0</span><span class="token punctuation">,</span> <span class="token number">0x8e3c5b2f</span><span class="token punctuation">,</span> <span class="token number">0x8e7594b7</span><span class="token punctuation">,</span>
		<span class="token number">0x8ff6e2fb</span><span class="token punctuation">,</span> <span class="token number">0xf2122b64</span><span class="token punctuation">,</span> <span class="token number">0x8888b812</span><span class="token punctuation">,</span> <span class="token number">0x900df01c</span><span class="token punctuation">,</span>
		<span class="token number">0x4fad5ea0</span><span class="token punctuation">,</span> <span class="token number">0x688fc31c</span><span class="token punctuation">,</span> <span class="token number">0xd1cff191</span><span class="token punctuation">,</span> <span class="token number">0xb3a8c1ad</span><span class="token punctuation">,</span>
		<span class="token number">0x2f2f2218</span><span class="token punctuation">,</span> <span class="token number">0xbe0e1777</span><span class="token punctuation">,</span> <span class="token number">0xea752dfe</span><span class="token punctuation">,</span> <span class="token number">0x8b021fa1</span><span class="token punctuation">,</span>
		<span class="token number">0xe5a0cc0f</span><span class="token punctuation">,</span> <span class="token number">0xb56f74e8</span><span class="token punctuation">,</span> <span class="token number">0x18acf3d6</span><span class="token punctuation">,</span> <span class="token number">0xce89e299</span><span class="token punctuation">,</span>
		<span class="token number">0xb4a84fe0</span><span class="token punctuation">,</span> <span class="token number">0xfd13e0b7</span><span class="token punctuation">,</span> <span class="token number">0x7cc43b81</span><span class="token punctuation">,</span> <span class="token number">0xd2ada8d9</span><span class="token punctuation">,</span>
		<span class="token number">0x165fa266</span><span class="token punctuation">,</span> <span class="token number">0x80957705</span><span class="token punctuation">,</span> <span class="token number">0x93cc7314</span><span class="token punctuation">,</span> <span class="token number">0x211a1477</span><span class="token punctuation">,</span>
		<span class="token number">0xe6ad2065</span><span class="token punctuation">,</span> <span class="token number">0x77b5fa86</span><span class="token punctuation">,</span> <span class="token number">0xc75442f5</span><span class="token punctuation">,</span> <span class="token number">0xfb9d35cf</span><span class="token punctuation">,</span>
		<span class="token number">0xebcdaf0c</span><span class="token punctuation">,</span> <span class="token number">0x7b3e89a0</span><span class="token punctuation">,</span> <span class="token number">0xd6411bd3</span><span class="token punctuation">,</span> <span class="token number">0xae1e7e49</span><span class="token punctuation">,</span>
		<span class="token number">0x00250e2d</span><span class="token punctuation">,</span> <span class="token number">0x2071b35e</span><span class="token punctuation">,</span> <span class="token number">0x226800bb</span><span class="token punctuation">,</span> <span class="token number">0x57b8e0af</span><span class="token punctuation">,</span>
		<span class="token number">0x2464369b</span><span class="token punctuation">,</span> <span class="token number">0xf009b91e</span><span class="token punctuation">,</span> <span class="token number">0x5563911d</span><span class="token punctuation">,</span> <span class="token number">0x59dfa6aa</span><span class="token punctuation">,</span>
		<span class="token number">0x78c14389</span><span class="token punctuation">,</span> <span class="token number">0xd95a537f</span><span class="token punctuation">,</span> <span class="token number">0x207d5ba2</span><span class="token punctuation">,</span> <span class="token number">0x02e5b9c5</span><span class="token punctuation">,</span>
		<span class="token number">0x83260376</span><span class="token punctuation">,</span> <span class="token number">0x6295cfa9</span><span class="token punctuation">,</span> <span class="token number">0x11c81968</span><span class="token punctuation">,</span> <span class="token number">0x4e734a41</span><span class="token punctuation">,</span>
		<span class="token number">0xb3472dca</span><span class="token punctuation">,</span> <span class="token number">0x7b14a94a</span><span class="token punctuation">,</span> <span class="token number">0x1b510052</span><span class="token punctuation">,</span> <span class="token number">0x9a532915</span><span class="token punctuation">,</span>
		<span class="token number">0xd60f573f</span><span class="token punctuation">,</span> <span class="token number">0xbc9bc6e4</span><span class="token punctuation">,</span> <span class="token number">0x2b60a476</span><span class="token punctuation">,</span> <span class="token number">0x81e67400</span><span class="token punctuation">,</span>
		<span class="token number">0x08ba6fb5</span><span class="token punctuation">,</span> <span class="token number">0x571be91f</span><span class="token punctuation">,</span> <span class="token number">0xf296ec6b</span><span class="token punctuation">,</span> <span class="token number">0x2a0dd915</span><span class="token punctuation">,</span>
		<span class="token number">0xb6636521</span><span class="token punctuation">,</span> <span class="token number">0xe7b9f9b6</span><span class="token punctuation">,</span> <span class="token number">0xff34052e</span><span class="token punctuation">,</span> <span class="token number">0xc5855664</span><span class="token punctuation">,</span>
		<span class="token number">0x53b02d5d</span><span class="token punctuation">,</span> <span class="token number">0xa99f8fa1</span><span class="token punctuation">,</span> <span class="token number">0x08ba4799</span><span class="token punctuation">,</span> <span class="token number">0x6e85076a</span><span class="token punctuation">,</span>
		<span class="token number">0x4b7a70e9</span><span class="token punctuation">,</span> <span class="token number">0xb5b32944</span><span class="token punctuation">,</span> <span class="token number">0xdb75092e</span><span class="token punctuation">,</span> <span class="token number">0xc4192623</span><span class="token punctuation">,</span>
		<span class="token number">0xad6ea6b0</span><span class="token punctuation">,</span> <span class="token number">0x49a7df7d</span><span class="token punctuation">,</span> <span class="token number">0x9cee60b8</span><span class="token punctuation">,</span> <span class="token number">0x8fedb266</span><span class="token punctuation">,</span>
		<span class="token number">0xecaa8c71</span><span class="token punctuation">,</span> <span class="token number">0x699a17ff</span><span class="token punctuation">,</span> <span class="token number">0x5664526c</span><span class="token punctuation">,</span> <span class="token number">0xc2b19ee1</span><span class="token punctuation">,</span>
		<span class="token number">0x193602a5</span><span class="token punctuation">,</span> <span class="token number">0x75094c29</span><span class="token punctuation">,</span> <span class="token number">0xa0591340</span><span class="token punctuation">,</span> <span class="token number">0xe4183a3e</span><span class="token punctuation">,</span>
		<span class="token number">0x3f54989a</span><span class="token punctuation">,</span> <span class="token number">0x5b429d65</span><span class="token punctuation">,</span> <span class="token number">0x6b8fe4d6</span><span class="token punctuation">,</span> <span class="token number">0x99f73fd6</span><span class="token punctuation">,</span>
		<span class="token number">0xa1d29c07</span><span class="token punctuation">,</span> <span class="token number">0xefe830f5</span><span class="token punctuation">,</span> <span class="token number">0x4d2d38e6</span><span class="token punctuation">,</span> <span class="token number">0xf0255dc1</span><span class="token punctuation">,</span>
		<span class="token number">0x4cdd2086</span><span class="token punctuation">,</span> <span class="token number">0x8470eb26</span><span class="token punctuation">,</span> <span class="token number">0x6382e9c6</span><span class="token punctuation">,</span> <span class="token number">0x021ecc5e</span><span class="token punctuation">,</span>
		<span class="token number">0x09686b3f</span><span class="token punctuation">,</span> <span class="token number">0x3ebaefc9</span><span class="token punctuation">,</span> <span class="token number">0x3c971814</span><span class="token punctuation">,</span> <span class="token number">0x6b6a70a1</span><span class="token punctuation">,</span>
		<span class="token number">0x687f3584</span><span class="token punctuation">,</span> <span class="token number">0x52a0e286</span><span class="token punctuation">,</span> <span class="token number">0xb79c5305</span><span class="token punctuation">,</span> <span class="token number">0xaa500737</span><span class="token punctuation">,</span>
		<span class="token number">0x3e07841c</span><span class="token punctuation">,</span> <span class="token number">0x7fdeae5c</span><span class="token punctuation">,</span> <span class="token number">0x8e7d44ec</span><span class="token punctuation">,</span> <span class="token number">0x5716f2b8</span><span class="token punctuation">,</span>
		<span class="token number">0xb03ada37</span><span class="token punctuation">,</span> <span class="token number">0xf0500c0d</span><span class="token punctuation">,</span> <span class="token number">0xf01c1f04</span><span class="token punctuation">,</span> <span class="token number">0x0200b3ff</span><span class="token punctuation">,</span>
		<span class="token number">0xae0cf51a</span><span class="token punctuation">,</span> <span class="token number">0x3cb574b2</span><span class="token punctuation">,</span> <span class="token number">0x25837a58</span><span class="token punctuation">,</span> <span class="token number">0xdc0921bd</span><span class="token punctuation">,</span>
		<span class="token number">0xd19113f9</span><span class="token punctuation">,</span> <span class="token number">0x7ca92ff6</span><span class="token punctuation">,</span> <span class="token number">0x94324773</span><span class="token punctuation">,</span> <span class="token number">0x22f54701</span><span class="token punctuation">,</span>
		<span class="token number">0x3ae5e581</span><span class="token punctuation">,</span> <span class="token number">0x37c2dadc</span><span class="token punctuation">,</span> <span class="token number">0xc8b57634</span><span class="token punctuation">,</span> <span class="token number">0x9af3dda7</span><span class="token punctuation">,</span>
		<span class="token number">0xa9446146</span><span class="token punctuation">,</span> <span class="token number">0x0fd0030e</span><span class="token punctuation">,</span> <span class="token number">0xecc8c73e</span><span class="token punctuation">,</span> <span class="token number">0xa4751e41</span><span class="token punctuation">,</span>
		<span class="token number">0xe238cd99</span><span class="token punctuation">,</span> <span class="token number">0x3bea0e2f</span><span class="token punctuation">,</span> <span class="token number">0x3280bba1</span><span class="token punctuation">,</span> <span class="token number">0x183eb331</span><span class="token punctuation">,</span>
		<span class="token number">0x4e548b38</span><span class="token punctuation">,</span> <span class="token number">0x4f6db908</span><span class="token punctuation">,</span> <span class="token number">0x6f420d03</span><span class="token punctuation">,</span> <span class="token number">0xf60a04bf</span><span class="token punctuation">,</span>
		<span class="token number">0x2cb81290</span><span class="token punctuation">,</span> <span class="token number">0x24977c79</span><span class="token punctuation">,</span> <span class="token number">0x5679b072</span><span class="token punctuation">,</span> <span class="token number">0xbcaf89af</span><span class="token punctuation">,</span>
		<span class="token number">0xde9a771f</span><span class="token punctuation">,</span> <span class="token number">0xd9930810</span><span class="token punctuation">,</span> <span class="token number">0xb38bae12</span><span class="token punctuation">,</span> <span class="token number">0xdccf3f2e</span><span class="token punctuation">,</span>
		<span class="token number">0x5512721f</span><span class="token punctuation">,</span> <span class="token number">0x2e6b7124</span><span class="token punctuation">,</span> <span class="token number">0x501adde6</span><span class="token punctuation">,</span> <span class="token number">0x9f84cd87</span><span class="token punctuation">,</span>
		<span class="token number">0x7a584718</span><span class="token punctuation">,</span> <span class="token number">0x7408da17</span><span class="token punctuation">,</span> <span class="token number">0xbc9f9abc</span><span class="token punctuation">,</span> <span class="token number">0xe94b7d8c</span><span class="token punctuation">,</span>
		<span class="token number">0xec7aec3a</span><span class="token punctuation">,</span> <span class="token number">0xdb851dfa</span><span class="token punctuation">,</span> <span class="token number">0x63094366</span><span class="token punctuation">,</span> <span class="token number">0xc464c3d2</span><span class="token punctuation">,</span>
		<span class="token number">0xef1c1847</span><span class="token punctuation">,</span> <span class="token number">0x3215d908</span><span class="token punctuation">,</span> <span class="token number">0xdd433b37</span><span class="token punctuation">,</span> <span class="token number">0x24c2ba16</span><span class="token punctuation">,</span>
		<span class="token number">0x12a14d43</span><span class="token punctuation">,</span> <span class="token number">0x2a65c451</span><span class="token punctuation">,</span> <span class="token number">0x50940002</span><span class="token punctuation">,</span> <span class="token number">0x133ae4dd</span><span class="token punctuation">,</span>
		<span class="token number">0x71dff89e</span><span class="token punctuation">,</span> <span class="token number">0x10314e55</span><span class="token punctuation">,</span> <span class="token number">0x81ac77d6</span><span class="token punctuation">,</span> <span class="token number">0x5f11199b</span><span class="token punctuation">,</span>
		<span class="token number">0x043556f1</span><span class="token punctuation">,</span> <span class="token number">0xd7a3c76b</span><span class="token punctuation">,</span> <span class="token number">0x3c11183b</span><span class="token punctuation">,</span> <span class="token number">0x5924a509</span><span class="token punctuation">,</span>
		<span class="token number">0xf28fe6ed</span><span class="token punctuation">,</span> <span class="token number">0x97f1fbfa</span><span class="token punctuation">,</span> <span class="token number">0x9ebabf2c</span><span class="token punctuation">,</span> <span class="token number">0x1e153c6e</span><span class="token punctuation">,</span>
		<span class="token number">0x86e34570</span><span class="token punctuation">,</span> <span class="token number">0xeae96fb1</span><span class="token punctuation">,</span> <span class="token number">0x860e5e0a</span><span class="token punctuation">,</span> <span class="token number">0x5a3e2ab3</span><span class="token punctuation">,</span>
		<span class="token number">0x771fe71c</span><span class="token punctuation">,</span> <span class="token number">0x4e3d06fa</span><span class="token punctuation">,</span> <span class="token number">0x2965dcb9</span><span class="token punctuation">,</span> <span class="token number">0x99e71d0f</span><span class="token punctuation">,</span>
		<span class="token number">0x803e89d6</span><span class="token punctuation">,</span> <span class="token number">0x5266c825</span><span class="token punctuation">,</span> <span class="token number">0x2e4cc978</span><span class="token punctuation">,</span> <span class="token number">0x9c10b36a</span><span class="token punctuation">,</span>
		<span class="token number">0xc6150eba</span><span class="token punctuation">,</span> <span class="token number">0x94e2ea78</span><span class="token punctuation">,</span> <span class="token number">0xa5fc3c53</span><span class="token punctuation">,</span> <span class="token number">0x1e0a2df4</span><span class="token punctuation">,</span>
		<span class="token number">0xf2f74ea7</span><span class="token punctuation">,</span> <span class="token number">0x361d2b3d</span><span class="token punctuation">,</span> <span class="token number">0x1939260f</span><span class="token punctuation">,</span> <span class="token number">0x19c27960</span><span class="token punctuation">,</span>
		<span class="token number">0x5223a708</span><span class="token punctuation">,</span> <span class="token number">0xf71312b6</span><span class="token punctuation">,</span> <span class="token number">0xebadfe6e</span><span class="token punctuation">,</span> <span class="token number">0xeac31f66</span><span class="token punctuation">,</span>
		<span class="token number">0xe3bc4595</span><span class="token punctuation">,</span> <span class="token number">0xa67bc883</span><span class="token punctuation">,</span> <span class="token number">0xb17f37d1</span><span class="token punctuation">,</span> <span class="token number">0x018cff28</span><span class="token punctuation">,</span>
		<span class="token number">0xc332ddef</span><span class="token punctuation">,</span> <span class="token number">0xbe6c5aa5</span><span class="token punctuation">,</span> <span class="token number">0x65582185</span><span class="token punctuation">,</span> <span class="token number">0x68ab9802</span><span class="token punctuation">,</span>
		<span class="token number">0xeecea50f</span><span class="token punctuation">,</span> <span class="token number">0xdb2f953b</span><span class="token punctuation">,</span> <span class="token number">0x2aef7dad</span><span class="token punctuation">,</span> <span class="token number">0x5b6e2f84</span><span class="token punctuation">,</span>
		<span class="token number">0x1521b628</span><span class="token punctuation">,</span> <span class="token number">0x29076170</span><span class="token punctuation">,</span> <span class="token number">0xecdd4775</span><span class="token punctuation">,</span> <span class="token number">0x619f1510</span><span class="token punctuation">,</span>
		<span class="token number">0x13cca830</span><span class="token punctuation">,</span> <span class="token number">0xeb61bd96</span><span class="token punctuation">,</span> <span class="token number">0x0334fe1e</span><span class="token punctuation">,</span> <span class="token number">0xaa0363cf</span><span class="token punctuation">,</span>
		<span class="token number">0xb5735c90</span><span class="token punctuation">,</span> <span class="token number">0x4c70a239</span><span class="token punctuation">,</span> <span class="token number">0xd59e9e0b</span><span class="token punctuation">,</span> <span class="token number">0xcbaade14</span><span class="token punctuation">,</span>
		<span class="token number">0xeecc86bc</span><span class="token punctuation">,</span> <span class="token number">0x60622ca7</span><span class="token punctuation">,</span> <span class="token number">0x9cab5cab</span><span class="token punctuation">,</span> <span class="token number">0xb2f3846e</span><span class="token punctuation">,</span>
		<span class="token number">0x648b1eaf</span><span class="token punctuation">,</span> <span class="token number">0x19bdf0ca</span><span class="token punctuation">,</span> <span class="token number">0xa02369b9</span><span class="token punctuation">,</span> <span class="token number">0x655abb50</span><span class="token punctuation">,</span>
		<span class="token number">0x40685a32</span><span class="token punctuation">,</span> <span class="token number">0x3c2ab4b3</span><span class="token punctuation">,</span> <span class="token number">0x319ee9d5</span><span class="token punctuation">,</span> <span class="token number">0xc021b8f7</span><span class="token punctuation">,</span>
		<span class="token number">0x9b540b19</span><span class="token punctuation">,</span> <span class="token number">0x875fa099</span><span class="token punctuation">,</span> <span class="token number">0x95f7997e</span><span class="token punctuation">,</span> <span class="token number">0x623d7da8</span><span class="token punctuation">,</span>
		<span class="token number">0xf837889a</span><span class="token punctuation">,</span> <span class="token number">0x97e32d77</span><span class="token punctuation">,</span> <span class="token number">0x11ed935f</span><span class="token punctuation">,</span> <span class="token number">0x16681281</span><span class="token punctuation">,</span>
		<span class="token number">0x0e358829</span><span class="token punctuation">,</span> <span class="token number">0xc7e61fd6</span><span class="token punctuation">,</span> <span class="token number">0x96dedfa1</span><span class="token punctuation">,</span> <span class="token number">0x7858ba99</span><span class="token punctuation">,</span>
		<span class="token number">0x57f584a5</span><span class="token punctuation">,</span> <span class="token number">0x1b227263</span><span class="token punctuation">,</span> <span class="token number">0x9b83c3ff</span><span class="token punctuation">,</span> <span class="token number">0x1ac24696</span><span class="token punctuation">,</span>
		<span class="token number">0xcdb30aeb</span><span class="token punctuation">,</span> <span class="token number">0x532e3054</span><span class="token punctuation">,</span> <span class="token number">0x8fd948e4</span><span class="token punctuation">,</span> <span class="token number">0x6dbc3128</span><span class="token punctuation">,</span>
		<span class="token number">0x58ebf2ef</span><span class="token punctuation">,</span> <span class="token number">0x34c6ffea</span><span class="token punctuation">,</span> <span class="token number">0xfe28ed61</span><span class="token punctuation">,</span> <span class="token number">0xee7c3c73</span><span class="token punctuation">,</span>
		<span class="token number">0x5d4a14d9</span><span class="token punctuation">,</span> <span class="token number">0xe864b7e3</span><span class="token punctuation">,</span> <span class="token number">0x42105d14</span><span class="token punctuation">,</span> <span class="token number">0x203e13e0</span><span class="token punctuation">,</span>
		<span class="token number">0x45eee2b6</span><span class="token punctuation">,</span> <span class="token number">0xa3aaabea</span><span class="token punctuation">,</span> <span class="token number">0xdb6c4f15</span><span class="token punctuation">,</span> <span class="token number">0xfacb4fd0</span><span class="token punctuation">,</span>
		<span class="token number">0xc742f442</span><span class="token punctuation">,</span> <span class="token number">0xef6abbb5</span><span class="token punctuation">,</span> <span class="token number">0x654f3b1d</span><span class="token punctuation">,</span> <span class="token number">0x41cd2105</span><span class="token punctuation">,</span>
		<span class="token number">0xd81e799e</span><span class="token punctuation">,</span> <span class="token number">0x86854dc7</span><span class="token punctuation">,</span> <span class="token number">0xe44b476a</span><span class="token punctuation">,</span> <span class="token number">0x3d816250</span><span class="token punctuation">,</span>
		<span class="token number">0xcf62a1f2</span><span class="token punctuation">,</span> <span class="token number">0x5b8d2646</span><span class="token punctuation">,</span> <span class="token number">0xfc8883a0</span><span class="token punctuation">,</span> <span class="token number">0xc1c7b6a3</span><span class="token punctuation">,</span>
		<span class="token number">0x7f1524c3</span><span class="token punctuation">,</span> <span class="token number">0x69cb7492</span><span class="token punctuation">,</span> <span class="token number">0x47848a0b</span><span class="token punctuation">,</span> <span class="token number">0x5692b285</span><span class="token punctuation">,</span>
		<span class="token number">0x095bbf00</span><span class="token punctuation">,</span> <span class="token number">0xad19489d</span><span class="token punctuation">,</span> <span class="token number">0x1462b174</span><span class="token punctuation">,</span> <span class="token number">0x23820e00</span><span class="token punctuation">,</span>
		<span class="token number">0x58428d2a</span><span class="token punctuation">,</span> <span class="token number">0x0c55f5ea</span><span class="token punctuation">,</span> <span class="token number">0x1dadf43e</span><span class="token punctuation">,</span> <span class="token number">0x233f7061</span><span class="token punctuation">,</span>
		<span class="token number">0x3372f092</span><span class="token punctuation">,</span> <span class="token number">0x8d937e41</span><span class="token punctuation">,</span> <span class="token number">0xd65fecf1</span><span class="token punctuation">,</span> <span class="token number">0x6c223bdb</span><span class="token punctuation">,</span>
		<span class="token number">0x7cde3759</span><span class="token punctuation">,</span> <span class="token number">0xcbee7460</span><span class="token punctuation">,</span> <span class="token number">0x4085f2a7</span><span class="token punctuation">,</span> <span class="token number">0xce77326e</span><span class="token punctuation">,</span>
		<span class="token number">0xa6078084</span><span class="token punctuation">,</span> <span class="token number">0x19f8509e</span><span class="token punctuation">,</span> <span class="token number">0xe8efd855</span><span class="token punctuation">,</span> <span class="token number">0x61d99735</span><span class="token punctuation">,</span>
		<span class="token number">0xa969a7aa</span><span class="token punctuation">,</span> <span class="token number">0xc50c06c2</span><span class="token punctuation">,</span> <span class="token number">0x5a04abfc</span><span class="token punctuation">,</span> <span class="token number">0x800bcadc</span><span class="token punctuation">,</span>
		<span class="token number">0x9e447a2e</span><span class="token punctuation">,</span> <span class="token number">0xc3453484</span><span class="token punctuation">,</span> <span class="token number">0xfdd56705</span><span class="token punctuation">,</span> <span class="token number">0x0e1e9ec9</span><span class="token punctuation">,</span>
		<span class="token number">0xdb73dbd3</span><span class="token punctuation">,</span> <span class="token number">0x105588cd</span><span class="token punctuation">,</span> <span class="token number">0x675fda79</span><span class="token punctuation">,</span> <span class="token number">0xe3674340</span><span class="token punctuation">,</span>
		<span class="token number">0xc5c43465</span><span class="token punctuation">,</span> <span class="token number">0x713e38d8</span><span class="token punctuation">,</span> <span class="token number">0x3d28f89e</span><span class="token punctuation">,</span> <span class="token number">0xf16dff20</span><span class="token punctuation">,</span>
		<span class="token number">0x153e21e7</span><span class="token punctuation">,</span> <span class="token number">0x8fb03d4a</span><span class="token punctuation">,</span> <span class="token number">0xe6e39f2b</span><span class="token punctuation">,</span> <span class="token number">0xdb83adf7</span><span class="token punctuation">,</span>
		<span class="token number">0xe93d5a68</span><span class="token punctuation">,</span> <span class="token number">0x948140f7</span><span class="token punctuation">,</span> <span class="token number">0xf64c261c</span><span class="token punctuation">,</span> <span class="token number">0x94692934</span><span class="token punctuation">,</span>
		<span class="token number">0x411520f7</span><span class="token punctuation">,</span> <span class="token number">0x7602d4f7</span><span class="token punctuation">,</span> <span class="token number">0xbcf46b2e</span><span class="token punctuation">,</span> <span class="token number">0xd4a20068</span><span class="token punctuation">,</span>
		<span class="token number">0xd4082471</span><span class="token punctuation">,</span> <span class="token number">0x3320f46a</span><span class="token punctuation">,</span> <span class="token number">0x43b7d4b7</span><span class="token punctuation">,</span> <span class="token number">0x500061af</span><span class="token punctuation">,</span>
		<span class="token number">0x1e39f62e</span><span class="token punctuation">,</span> <span class="token number">0x97244546</span><span class="token punctuation">,</span> <span class="token number">0x14214f74</span><span class="token punctuation">,</span> <span class="token number">0xbf8b8840</span><span class="token punctuation">,</span>
		<span class="token number">0x4d95fc1d</span><span class="token punctuation">,</span> <span class="token number">0x96b591af</span><span class="token punctuation">,</span> <span class="token number">0x70f4ddd3</span><span class="token punctuation">,</span> <span class="token number">0x66a02f45</span><span class="token punctuation">,</span>
		<span class="token number">0xbfbc09ec</span><span class="token punctuation">,</span> <span class="token number">0x03bd9785</span><span class="token punctuation">,</span> <span class="token number">0x7fac6dd0</span><span class="token punctuation">,</span> <span class="token number">0x31cb8504</span><span class="token punctuation">,</span>
		<span class="token number">0x96eb27b3</span><span class="token punctuation">,</span> <span class="token number">0x55fd3941</span><span class="token punctuation">,</span> <span class="token number">0xda2547e6</span><span class="token punctuation">,</span> <span class="token number">0xabca0a9a</span><span class="token punctuation">,</span>
		<span class="token number">0x28507825</span><span class="token punctuation">,</span> <span class="token number">0x530429f4</span><span class="token punctuation">,</span> <span class="token number">0x0a2c86da</span><span class="token punctuation">,</span> <span class="token number">0xe9b66dfb</span><span class="token punctuation">,</span>
		<span class="token number">0x68dc1462</span><span class="token punctuation">,</span> <span class="token number">0xd7486900</span><span class="token punctuation">,</span> <span class="token number">0x680ec0a4</span><span class="token punctuation">,</span> <span class="token number">0x27a18dee</span><span class="token punctuation">,</span>
		<span class="token number">0x4f3ffea2</span><span class="token punctuation">,</span> <span class="token number">0xe887ad8c</span><span class="token punctuation">,</span> <span class="token number">0xb58ce006</span><span class="token punctuation">,</span> <span class="token number">0x7af4d6b6</span><span class="token punctuation">,</span>
		<span class="token number">0xaace1e7c</span><span class="token punctuation">,</span> <span class="token number">0xd3375fec</span><span class="token punctuation">,</span> <span class="token number">0xce78a399</span><span class="token punctuation">,</span> <span class="token number">0x406b2a42</span><span class="token punctuation">,</span>
		<span class="token number">0x20fe9e35</span><span class="token punctuation">,</span> <span class="token number">0xd9f385b9</span><span class="token punctuation">,</span> <span class="token number">0xee39d7ab</span><span class="token punctuation">,</span> <span class="token number">0x3b124e8b</span><span class="token punctuation">,</span>
		<span class="token number">0x1dc9faf7</span><span class="token punctuation">,</span> <span class="token number">0x4b6d1856</span><span class="token punctuation">,</span> <span class="token number">0x26a36631</span><span class="token punctuation">,</span> <span class="token number">0xeae397b2</span><span class="token punctuation">,</span>
		<span class="token number">0x3a6efa74</span><span class="token punctuation">,</span> <span class="token number">0xdd5b4332</span><span class="token punctuation">,</span> <span class="token number">0x6841e7f7</span><span class="token punctuation">,</span> <span class="token number">0xca7820fb</span><span class="token punctuation">,</span>
		<span class="token number">0xfb0af54e</span><span class="token punctuation">,</span> <span class="token number">0xd8feb397</span><span class="token punctuation">,</span> <span class="token number">0x454056ac</span><span class="token punctuation">,</span> <span class="token number">0xba489527</span><span class="token punctuation">,</span>
		<span class="token number">0x55533a3a</span><span class="token punctuation">,</span> <span class="token number">0x20838d87</span><span class="token punctuation">,</span> <span class="token number">0xfe6ba9b7</span><span class="token punctuation">,</span> <span class="token number">0xd096954b</span><span class="token punctuation">,</span>
		<span class="token number">0x55a867bc</span><span class="token punctuation">,</span> <span class="token number">0xa1159a58</span><span class="token punctuation">,</span> <span class="token number">0xcca92963</span><span class="token punctuation">,</span> <span class="token number">0x99e1db33</span><span class="token punctuation">,</span>
		<span class="token number">0xa62a4a56</span><span class="token punctuation">,</span> <span class="token number">0x3f3125f9</span><span class="token punctuation">,</span> <span class="token number">0x5ef47e1c</span><span class="token punctuation">,</span> <span class="token number">0x9029317c</span><span class="token punctuation">,</span>
		<span class="token number">0xfdf8e802</span><span class="token punctuation">,</span> <span class="token number">0x04272f70</span><span class="token punctuation">,</span> <span class="token number">0x80bb155c</span><span class="token punctuation">,</span> <span class="token number">0x05282ce3</span><span class="token punctuation">,</span>
		<span class="token number">0x95c11548</span><span class="token punctuation">,</span> <span class="token number">0xe4c66d22</span><span class="token punctuation">,</span> <span class="token number">0x48c1133f</span><span class="token punctuation">,</span> <span class="token number">0xc70f86dc</span><span class="token punctuation">,</span>
		<span class="token number">0x07f9c9ee</span><span class="token punctuation">,</span> <span class="token number">0x41041f0f</span><span class="token punctuation">,</span> <span class="token number">0x404779a4</span><span class="token punctuation">,</span> <span class="token number">0x5d886e17</span><span class="token punctuation">,</span>
		<span class="token number">0x325f51eb</span><span class="token punctuation">,</span> <span class="token number">0xd59bc0d1</span><span class="token punctuation">,</span> <span class="token number">0xf2bcc18f</span><span class="token punctuation">,</span> <span class="token number">0x41113564</span><span class="token punctuation">,</span>
		<span class="token number">0x257b7834</span><span class="token punctuation">,</span> <span class="token number">0x602a9c60</span><span class="token punctuation">,</span> <span class="token number">0xdff8e8a3</span><span class="token punctuation">,</span> <span class="token number">0x1f636c1b</span><span class="token punctuation">,</span>
		<span class="token number">0x0e12b4c2</span><span class="token punctuation">,</span> <span class="token number">0x02e1329e</span><span class="token punctuation">,</span> <span class="token number">0xaf664fd1</span><span class="token punctuation">,</span> <span class="token number">0xcad18115</span><span class="token punctuation">,</span>
		<span class="token number">0x6b2395e0</span><span class="token punctuation">,</span> <span class="token number">0x333e92e1</span><span class="token punctuation">,</span> <span class="token number">0x3b240b62</span><span class="token punctuation">,</span> <span class="token number">0xeebeb922</span><span class="token punctuation">,</span>
		<span class="token number">0x85b2a20e</span><span class="token punctuation">,</span> <span class="token number">0xe6ba0d99</span><span class="token punctuation">,</span> <span class="token number">0xde720c8c</span><span class="token punctuation">,</span> <span class="token number">0x2da2f728</span><span class="token punctuation">,</span>
		<span class="token number">0xd0127845</span><span class="token punctuation">,</span> <span class="token number">0x95b794fd</span><span class="token punctuation">,</span> <span class="token number">0x647d0862</span><span class="token punctuation">,</span> <span class="token number">0xe7ccf5f0</span><span class="token punctuation">,</span>
		<span class="token number">0x5449a36f</span><span class="token punctuation">,</span> <span class="token number">0x877d48fa</span><span class="token punctuation">,</span> <span class="token number">0xc39dfd27</span><span class="token punctuation">,</span> <span class="token number">0xf33e8d1e</span><span class="token punctuation">,</span>
		<span class="token number">0x0a476341</span><span class="token punctuation">,</span> <span class="token number">0x992eff74</span><span class="token punctuation">,</span> <span class="token number">0x3a6f6eab</span><span class="token punctuation">,</span> <span class="token number">0xf4f8fd37</span><span class="token punctuation">,</span>
		<span class="token number">0xa812dc60</span><span class="token punctuation">,</span> <span class="token number">0xa1ebddf8</span><span class="token punctuation">,</span> <span class="token number">0x991be14c</span><span class="token punctuation">,</span> <span class="token number">0xdb6e6b0d</span><span class="token punctuation">,</span>
		<span class="token number">0xc67b5510</span><span class="token punctuation">,</span> <span class="token number">0x6d672c37</span><span class="token punctuation">,</span> <span class="token number">0x2765d43b</span><span class="token punctuation">,</span> <span class="token number">0xdcd0e804</span><span class="token punctuation">,</span>
		<span class="token number">0xf1290dc7</span><span class="token punctuation">,</span> <span class="token number">0xcc00ffa3</span><span class="token punctuation">,</span> <span class="token number">0xb5390f92</span><span class="token punctuation">,</span> <span class="token number">0x690fed0b</span><span class="token punctuation">,</span>
		<span class="token number">0x667b9ffb</span><span class="token punctuation">,</span> <span class="token number">0xcedb7d9c</span><span class="token punctuation">,</span> <span class="token number">0xa091cf0b</span><span class="token punctuation">,</span> <span class="token number">0xd9155ea3</span><span class="token punctuation">,</span>
		<span class="token number">0xbb132f88</span><span class="token punctuation">,</span> <span class="token number">0x515bad24</span><span class="token punctuation">,</span> <span class="token number">0x7b9479bf</span><span class="token punctuation">,</span> <span class="token number">0x763bd6eb</span><span class="token punctuation">,</span>
		<span class="token number">0x37392eb3</span><span class="token punctuation">,</span> <span class="token number">0xcc115979</span><span class="token punctuation">,</span> <span class="token number">0x8026e297</span><span class="token punctuation">,</span> <span class="token number">0xf42e312d</span><span class="token punctuation">,</span>
		<span class="token number">0x6842ada7</span><span class="token punctuation">,</span> <span class="token number">0xc66a2b3b</span><span class="token punctuation">,</span> <span class="token number">0x12754ccc</span><span class="token punctuation">,</span> <span class="token number">0x782ef11c</span><span class="token punctuation">,</span>
		<span class="token number">0x6a124237</span><span class="token punctuation">,</span> <span class="token number">0xb79251e7</span><span class="token punctuation">,</span> <span class="token number">0x06a1bbe6</span><span class="token punctuation">,</span> <span class="token number">0x4bfb6350</span><span class="token punctuation">,</span>
		<span class="token number">0x1a6b1018</span><span class="token punctuation">,</span> <span class="token number">0x11caedfa</span><span class="token punctuation">,</span> <span class="token number">0x3d25bdd8</span><span class="token punctuation">,</span> <span class="token number">0xe2e1c3c9</span><span class="token punctuation">,</span>
		<span class="token number">0x44421659</span><span class="token punctuation">,</span> <span class="token number">0x0a121386</span><span class="token punctuation">,</span> <span class="token number">0xd90cec6e</span><span class="token punctuation">,</span> <span class="token number">0xd5abea2a</span><span class="token punctuation">,</span>
		<span class="token number">0x64af674e</span><span class="token punctuation">,</span> <span class="token number">0xda86a85f</span><span class="token punctuation">,</span> <span class="token number">0xbebfe988</span><span class="token punctuation">,</span> <span class="token number">0x64e4c3fe</span><span class="token punctuation">,</span>
		<span class="token number">0x9dbc8057</span><span class="token punctuation">,</span> <span class="token number">0xf0f7c086</span><span class="token punctuation">,</span> <span class="token number">0x60787bf8</span><span class="token punctuation">,</span> <span class="token number">0x6003604d</span><span class="token punctuation">,</span>
		<span class="token number">0xd1fd8346</span><span class="token punctuation">,</span> <span class="token number">0xf6381fb0</span><span class="token punctuation">,</span> <span class="token number">0x7745ae04</span><span class="token punctuation">,</span> <span class="token number">0xd736fccc</span><span class="token punctuation">,</span>
		<span class="token number">0x83426b33</span><span class="token punctuation">,</span> <span class="token number">0xf01eab71</span><span class="token punctuation">,</span> <span class="token number">0xb0804187</span><span class="token punctuation">,</span> <span class="token number">0x3c005e5f</span><span class="token punctuation">,</span>
		<span class="token number">0x77a057be</span><span class="token punctuation">,</span> <span class="token number">0xbde8ae24</span><span class="token punctuation">,</span> <span class="token number">0x55464299</span><span class="token punctuation">,</span> <span class="token number">0xbf582e61</span><span class="token punctuation">,</span>
		<span class="token number">0x4e58f48f</span><span class="token punctuation">,</span> <span class="token number">0xf2ddfda2</span><span class="token punctuation">,</span> <span class="token number">0xf474ef38</span><span class="token punctuation">,</span> <span class="token number">0x8789bdc2</span><span class="token punctuation">,</span>
		<span class="token number">0x5366f9c3</span><span class="token punctuation">,</span> <span class="token number">0xc8b38e74</span><span class="token punctuation">,</span> <span class="token number">0xb475f255</span><span class="token punctuation">,</span> <span class="token number">0x46fcd9b9</span><span class="token punctuation">,</span>
		<span class="token number">0x7aeb2661</span><span class="token punctuation">,</span> <span class="token number">0x8b1ddf84</span><span class="token punctuation">,</span> <span class="token number">0x846a0e79</span><span class="token punctuation">,</span> <span class="token number">0x915f95e2</span><span class="token punctuation">,</span>
		<span class="token number">0x466e598e</span><span class="token punctuation">,</span> <span class="token number">0x20b45770</span><span class="token punctuation">,</span> <span class="token number">0x8cd55591</span><span class="token punctuation">,</span> <span class="token number">0xc902de4c</span><span class="token punctuation">,</span>
		<span class="token number">0xb90bace1</span><span class="token punctuation">,</span> <span class="token number">0xbb8205d0</span><span class="token punctuation">,</span> <span class="token number">0x11a86248</span><span class="token punctuation">,</span> <span class="token number">0x7574a99e</span><span class="token punctuation">,</span>
		<span class="token number">0xb77f19b6</span><span class="token punctuation">,</span> <span class="token number">0xe0a9dc09</span><span class="token punctuation">,</span> <span class="token number">0x662d09a1</span><span class="token punctuation">,</span> <span class="token number">0xc4324633</span><span class="token punctuation">,</span>
		<span class="token number">0xe85a1f02</span><span class="token punctuation">,</span> <span class="token number">0x09f0be8c</span><span class="token punctuation">,</span> <span class="token number">0x4a99a025</span><span class="token punctuation">,</span> <span class="token number">0x1d6efe10</span><span class="token punctuation">,</span>
		<span class="token number">0x1ab93d1d</span><span class="token punctuation">,</span> <span class="token number">0x0ba5a4df</span><span class="token punctuation">,</span> <span class="token number">0xa186f20f</span><span class="token punctuation">,</span> <span class="token number">0x2868f169</span><span class="token punctuation">,</span>
		<span class="token number">0xdcb7da83</span><span class="token punctuation">,</span> <span class="token number">0x573906fe</span><span class="token punctuation">,</span> <span class="token number">0xa1e2ce9b</span><span class="token punctuation">,</span> <span class="token number">0x4fcd7f52</span><span class="token punctuation">,</span>
		<span class="token number">0x50115e01</span><span class="token punctuation">,</span> <span class="token number">0xa70683fa</span><span class="token punctuation">,</span> <span class="token number">0xa002b5c4</span><span class="token punctuation">,</span> <span class="token number">0x0de6d027</span><span class="token punctuation">,</span>
		<span class="token number">0x9af88c27</span><span class="token punctuation">,</span> <span class="token number">0x773f8641</span><span class="token punctuation">,</span> <span class="token number">0xc3604c06</span><span class="token punctuation">,</span> <span class="token number">0x61a806b5</span><span class="token punctuation">,</span>
		<span class="token number">0xf0177a28</span><span class="token punctuation">,</span> <span class="token number">0xc0f586e0</span><span class="token punctuation">,</span> <span class="token number">0x006058aa</span><span class="token punctuation">,</span> <span class="token number">0x30dc7d62</span><span class="token punctuation">,</span>
		<span class="token number">0x11e69ed7</span><span class="token punctuation">,</span> <span class="token number">0x2338ea63</span><span class="token punctuation">,</span> <span class="token number">0x53c2dd94</span><span class="token punctuation">,</span> <span class="token number">0xc2c21634</span><span class="token punctuation">,</span>
		<span class="token number">0xbbcbee56</span><span class="token punctuation">,</span> <span class="token number">0x90bcb6de</span><span class="token punctuation">,</span> <span class="token number">0xebfc7da1</span><span class="token punctuation">,</span> <span class="token number">0xce591d76</span><span class="token punctuation">,</span>
		<span class="token number">0x6f05e409</span><span class="token punctuation">,</span> <span class="token number">0x4b7c0188</span><span class="token punctuation">,</span> <span class="token number">0x39720a3d</span><span class="token punctuation">,</span> <span class="token number">0x7c927c24</span><span class="token punctuation">,</span>
		<span class="token number">0x86e3725f</span><span class="token punctuation">,</span> <span class="token number">0x724d9db9</span><span class="token punctuation">,</span> <span class="token number">0x1ac15bb4</span><span class="token punctuation">,</span> <span class="token number">0xd39eb8fc</span><span class="token punctuation">,</span>
		<span class="token number">0xed545578</span><span class="token punctuation">,</span> <span class="token number">0x08fca5b5</span><span class="token punctuation">,</span> <span class="token number">0xd83d7cd3</span><span class="token punctuation">,</span> <span class="token number">0x4dad0fc4</span><span class="token punctuation">,</span>
		<span class="token number">0x1e50ef5e</span><span class="token punctuation">,</span> <span class="token number">0xb161e6f8</span><span class="token punctuation">,</span> <span class="token number">0xa28514d9</span><span class="token punctuation">,</span> <span class="token number">0x6c51133c</span><span class="token punctuation">,</span>
		<span class="token number">0x6fd5c7e7</span><span class="token punctuation">,</span> <span class="token number">0x56e14ec4</span><span class="token punctuation">,</span> <span class="token number">0x362abfce</span><span class="token punctuation">,</span> <span class="token number">0xddc6c837</span><span class="token punctuation">,</span>
		<span class="token number">0xd79a3234</span><span class="token punctuation">,</span> <span class="token number">0x92638212</span><span class="token punctuation">,</span> <span class="token number">0x670efa8e</span><span class="token punctuation">,</span> <span class="token number">0x406000e0</span><span class="token punctuation">,</span>
		<span class="token number">0x3a39ce37</span><span class="token punctuation">,</span> <span class="token number">0xd3faf5cf</span><span class="token punctuation">,</span> <span class="token number">0xabc27737</span><span class="token punctuation">,</span> <span class="token number">0x5ac52d1b</span><span class="token punctuation">,</span>
		<span class="token number">0x5cb0679e</span><span class="token punctuation">,</span> <span class="token number">0x4fa33742</span><span class="token punctuation">,</span> <span class="token number">0xd3822740</span><span class="token punctuation">,</span> <span class="token number">0x99bc9bbe</span><span class="token punctuation">,</span>
		<span class="token number">0xd5118e9d</span><span class="token punctuation">,</span> <span class="token number">0xbf0f7315</span><span class="token punctuation">,</span> <span class="token number">0xd62d1c7e</span><span class="token punctuation">,</span> <span class="token number">0xc700c47b</span><span class="token punctuation">,</span>
		<span class="token number">0xb78c1b6b</span><span class="token punctuation">,</span> <span class="token number">0x21a19045</span><span class="token punctuation">,</span> <span class="token number">0xb26eb1be</span><span class="token punctuation">,</span> <span class="token number">0x6a366eb4</span><span class="token punctuation">,</span>
		<span class="token number">0x5748ab2f</span><span class="token punctuation">,</span> <span class="token number">0xbc946e79</span><span class="token punctuation">,</span> <span class="token number">0xc6a376d2</span><span class="token punctuation">,</span> <span class="token number">0x6549c2c8</span><span class="token punctuation">,</span>
		<span class="token number">0x530ff8ee</span><span class="token punctuation">,</span> <span class="token number">0x468dde7d</span><span class="token punctuation">,</span> <span class="token number">0xd5730a1d</span><span class="token punctuation">,</span> <span class="token number">0x4cd04dc6</span><span class="token punctuation">,</span>
		<span class="token number">0x2939bbdb</span><span class="token punctuation">,</span> <span class="token number">0xa9ba4650</span><span class="token punctuation">,</span> <span class="token number">0xac9526e8</span><span class="token punctuation">,</span> <span class="token number">0xbe5ee304</span><span class="token punctuation">,</span>
		<span class="token number">0xa1fad5f0</span><span class="token punctuation">,</span> <span class="token number">0x6a2d519a</span><span class="token punctuation">,</span> <span class="token number">0x63ef8ce2</span><span class="token punctuation">,</span> <span class="token number">0x9a86ee22</span><span class="token punctuation">,</span>
		<span class="token number">0xc089c2b8</span><span class="token punctuation">,</span> <span class="token number">0x43242ef6</span><span class="token punctuation">,</span> <span class="token number">0xa51e03aa</span><span class="token punctuation">,</span> <span class="token number">0x9cf2d0a4</span><span class="token punctuation">,</span>
		<span class="token number">0x83c061ba</span><span class="token punctuation">,</span> <span class="token number">0x9be96a4d</span><span class="token punctuation">,</span> <span class="token number">0x8fe51550</span><span class="token punctuation">,</span> <span class="token number">0xba645bd6</span><span class="token punctuation">,</span>
		<span class="token number">0x2826a2f9</span><span class="token punctuation">,</span> <span class="token number">0xa73a3ae1</span><span class="token punctuation">,</span> <span class="token number">0x4ba99586</span><span class="token punctuation">,</span> <span class="token number">0xef5562e9</span><span class="token punctuation">,</span>
		<span class="token number">0xc72fefd3</span><span class="token punctuation">,</span> <span class="token number">0xf752f7da</span><span class="token punctuation">,</span> <span class="token number">0x3f046f69</span><span class="token punctuation">,</span> <span class="token number">0x77fa0a59</span><span class="token punctuation">,</span>
		<span class="token number">0x80e4a915</span><span class="token punctuation">,</span> <span class="token number">0x87b08601</span><span class="token punctuation">,</span> <span class="token number">0x9b09e6ad</span><span class="token punctuation">,</span> <span class="token number">0x3b3ee593</span><span class="token punctuation">,</span>
		<span class="token number">0xe990fd5a</span><span class="token punctuation">,</span> <span class="token number">0x9e34d797</span><span class="token punctuation">,</span> <span class="token number">0x2cf0b7d9</span><span class="token punctuation">,</span> <span class="token number">0x022b8b51</span><span class="token punctuation">,</span>
		<span class="token number">0x96d5ac3a</span><span class="token punctuation">,</span> <span class="token number">0x017da67d</span><span class="token punctuation">,</span> <span class="token number">0xd1cf3ed6</span><span class="token punctuation">,</span> <span class="token number">0x7c7d2d28</span><span class="token punctuation">,</span>
		<span class="token number">0x1f9f25cf</span><span class="token punctuation">,</span> <span class="token number">0xadf2b89b</span><span class="token punctuation">,</span> <span class="token number">0x5ad6b472</span><span class="token punctuation">,</span> <span class="token number">0x5a88f54c</span><span class="token punctuation">,</span>
		<span class="token number">0xe029ac71</span><span class="token punctuation">,</span> <span class="token number">0xe019a5e6</span><span class="token punctuation">,</span> <span class="token number">0x47b0acfd</span><span class="token punctuation">,</span> <span class="token number">0xed93fa9b</span><span class="token punctuation">,</span>
		<span class="token number">0xe8d3c48d</span><span class="token punctuation">,</span> <span class="token number">0x283b57cc</span><span class="token punctuation">,</span> <span class="token number">0xf8d56629</span><span class="token punctuation">,</span> <span class="token number">0x79132e28</span><span class="token punctuation">,</span>
		<span class="token number">0x785f0191</span><span class="token punctuation">,</span> <span class="token number">0xed756055</span><span class="token punctuation">,</span> <span class="token number">0xf7960e44</span><span class="token punctuation">,</span> <span class="token number">0xe3d35e8c</span><span class="token punctuation">,</span>
		<span class="token number">0x15056dd4</span><span class="token punctuation">,</span> <span class="token number">0x88f46dba</span><span class="token punctuation">,</span> <span class="token number">0x03a16125</span><span class="token punctuation">,</span> <span class="token number">0x0564f0bd</span><span class="token punctuation">,</span>
		<span class="token number">0xc3eb9e15</span><span class="token punctuation">,</span> <span class="token number">0x3c9057a2</span><span class="token punctuation">,</span> <span class="token number">0x97271aec</span><span class="token punctuation">,</span> <span class="token number">0xa93a072a</span><span class="token punctuation">,</span>
		<span class="token number">0x1b3f6d9b</span><span class="token punctuation">,</span> <span class="token number">0x1e6321f5</span><span class="token punctuation">,</span> <span class="token number">0xf59c66fb</span><span class="token punctuation">,</span> <span class="token number">0x26dcf319</span><span class="token punctuation">,</span>
		<span class="token number">0x7533d928</span><span class="token punctuation">,</span> <span class="token number">0xb155fdf5</span><span class="token punctuation">,</span> <span class="token number">0x03563482</span><span class="token punctuation">,</span> <span class="token number">0x8aba3cbb</span><span class="token punctuation">,</span>
		<span class="token number">0x28517711</span><span class="token punctuation">,</span> <span class="token number">0xc20ad9f8</span><span class="token punctuation">,</span> <span class="token number">0xabcc5167</span><span class="token punctuation">,</span> <span class="token number">0xccad925f</span><span class="token punctuation">,</span>
		<span class="token number">0x4de81751</span><span class="token punctuation">,</span> <span class="token number">0x3830dc8e</span><span class="token punctuation">,</span> <span class="token number">0x379d5862</span><span class="token punctuation">,</span> <span class="token number">0x9320f991</span><span class="token punctuation">,</span>
		<span class="token number">0xea7a90c2</span><span class="token punctuation">,</span> <span class="token number">0xfb3e7bce</span><span class="token punctuation">,</span> <span class="token number">0x5121ce64</span><span class="token punctuation">,</span> <span class="token number">0x774fbe32</span><span class="token punctuation">,</span>
		<span class="token number">0xa8b6e37e</span><span class="token punctuation">,</span> <span class="token number">0xc3293d46</span><span class="token punctuation">,</span> <span class="token number">0x48de5369</span><span class="token punctuation">,</span> <span class="token number">0x6413e680</span><span class="token punctuation">,</span>
		<span class="token number">0xa2ae0810</span><span class="token punctuation">,</span> <span class="token number">0xdd6db224</span><span class="token punctuation">,</span> <span class="token number">0x69852dfd</span><span class="token punctuation">,</span> <span class="token number">0x09072166</span><span class="token punctuation">,</span>
		<span class="token number">0xb39a460a</span><span class="token punctuation">,</span> <span class="token number">0x6445c0dd</span><span class="token punctuation">,</span> <span class="token number">0x586cdecf</span><span class="token punctuation">,</span> <span class="token number">0x1c20c8ae</span><span class="token punctuation">,</span>
		<span class="token number">0x5bbef7dd</span><span class="token punctuation">,</span> <span class="token number">0x1b588d40</span><span class="token punctuation">,</span> <span class="token number">0xccd2017f</span><span class="token punctuation">,</span> <span class="token number">0x6bb4e3bb</span><span class="token punctuation">,</span>
		<span class="token number">0xdda26a7e</span><span class="token punctuation">,</span> <span class="token number">0x3a59ff45</span><span class="token punctuation">,</span> <span class="token number">0x3e350a44</span><span class="token punctuation">,</span> <span class="token number">0xbcb4cdd5</span><span class="token punctuation">,</span>
		<span class="token number">0x72eacea8</span><span class="token punctuation">,</span> <span class="token number">0xfa6484bb</span><span class="token punctuation">,</span> <span class="token number">0x8d6612ae</span><span class="token punctuation">,</span> <span class="token number">0xbf3c6f47</span><span class="token punctuation">,</span>
		<span class="token number">0xd29be463</span><span class="token punctuation">,</span> <span class="token number">0x542f5d9e</span><span class="token punctuation">,</span> <span class="token number">0xaec2771b</span><span class="token punctuation">,</span> <span class="token number">0xf64e6370</span><span class="token punctuation">,</span>
		<span class="token number">0x740e0d8d</span><span class="token punctuation">,</span> <span class="token number">0xe75b1357</span><span class="token punctuation">,</span> <span class="token number">0xf8721671</span><span class="token punctuation">,</span> <span class="token number">0xaf537d5d</span><span class="token punctuation">,</span>
		<span class="token number">0x4040cb08</span><span class="token punctuation">,</span> <span class="token number">0x4eb4e2cc</span><span class="token punctuation">,</span> <span class="token number">0x34d2466a</span><span class="token punctuation">,</span> <span class="token number">0x0115af84</span><span class="token punctuation">,</span>
		<span class="token number">0xe1b00428</span><span class="token punctuation">,</span> <span class="token number">0x95983a1d</span><span class="token punctuation">,</span> <span class="token number">0x06b89fb4</span><span class="token punctuation">,</span> <span class="token number">0xce6ea048</span><span class="token punctuation">,</span>
		<span class="token number">0x6f3f3b82</span><span class="token punctuation">,</span> <span class="token number">0x3520ab82</span><span class="token punctuation">,</span> <span class="token number">0x011a1d4b</span><span class="token punctuation">,</span> <span class="token number">0x277227f8</span><span class="token punctuation">,</span>
		<span class="token number">0x611560b1</span><span class="token punctuation">,</span> <span class="token number">0xe7933fdc</span><span class="token punctuation">,</span> <span class="token number">0xbb3a792b</span><span class="token punctuation">,</span> <span class="token number">0x344525bd</span><span class="token punctuation">,</span>
		<span class="token number">0xa08839e1</span><span class="token punctuation">,</span> <span class="token number">0x51ce794b</span><span class="token punctuation">,</span> <span class="token number">0x2f32c9b7</span><span class="token punctuation">,</span> <span class="token number">0xa01fbac9</span><span class="token punctuation">,</span>
		<span class="token number">0xe01cc87e</span><span class="token punctuation">,</span> <span class="token number">0xbcc7d1f6</span><span class="token punctuation">,</span> <span class="token number">0xcf0111c3</span><span class="token punctuation">,</span> <span class="token number">0xa1e8aac7</span><span class="token punctuation">,</span>
		<span class="token number">0x1a908749</span><span class="token punctuation">,</span> <span class="token number">0xd44fbd9a</span><span class="token punctuation">,</span> <span class="token number">0xd0dadecb</span><span class="token punctuation">,</span> <span class="token number">0xd50ada38</span><span class="token punctuation">,</span>
		<span class="token number">0x0339c32a</span><span class="token punctuation">,</span> <span class="token number">0xc6913667</span><span class="token punctuation">,</span> <span class="token number">0x8df9317c</span><span class="token punctuation">,</span> <span class="token number">0xe0b12b4f</span><span class="token punctuation">,</span>
		<span class="token number">0xf79e59b7</span><span class="token punctuation">,</span> <span class="token number">0x43f5bb3a</span><span class="token punctuation">,</span> <span class="token number">0xf2d519ff</span><span class="token punctuation">,</span> <span class="token number">0x27d9459c</span><span class="token punctuation">,</span>
		<span class="token number">0xbf97222c</span><span class="token punctuation">,</span> <span class="token number">0x15e6fc2a</span><span class="token punctuation">,</span> <span class="token number">0x0f91fc71</span><span class="token punctuation">,</span> <span class="token number">0x9b941525</span><span class="token punctuation">,</span>
		<span class="token number">0xfae59361</span><span class="token punctuation">,</span> <span class="token number">0xceb69ceb</span><span class="token punctuation">,</span> <span class="token number">0xc2a86459</span><span class="token punctuation">,</span> <span class="token number">0x12baa8d1</span><span class="token punctuation">,</span>
		<span class="token number">0xb6c1075e</span><span class="token punctuation">,</span> <span class="token number">0xe3056a0c</span><span class="token punctuation">,</span> <span class="token number">0x10d25065</span><span class="token punctuation">,</span> <span class="token number">0xcb03a442</span><span class="token punctuation">,</span>
		<span class="token number">0xe0ec6e0e</span><span class="token punctuation">,</span> <span class="token number">0x1698db3b</span><span class="token punctuation">,</span> <span class="token number">0x4c98a0be</span><span class="token punctuation">,</span> <span class="token number">0x3278e964</span><span class="token punctuation">,</span>
		<span class="token number">0x9f1f9532</span><span class="token punctuation">,</span> <span class="token number">0xe0d392df</span><span class="token punctuation">,</span> <span class="token number">0xd3a0342b</span><span class="token punctuation">,</span> <span class="token number">0x8971f21e</span><span class="token punctuation">,</span>
		<span class="token number">0x1b0a7441</span><span class="token punctuation">,</span> <span class="token number">0x4ba3348c</span><span class="token punctuation">,</span> <span class="token number">0xc5be7120</span><span class="token punctuation">,</span> <span class="token number">0xc37632d8</span><span class="token punctuation">,</span>
		<span class="token number">0xdf359f8d</span><span class="token punctuation">,</span> <span class="token number">0x9b992f2e</span><span class="token punctuation">,</span> <span class="token number">0xe60b6f47</span><span class="token punctuation">,</span> <span class="token number">0x0fe3f11d</span><span class="token punctuation">,</span>
		<span class="token number">0xe54cda54</span><span class="token punctuation">,</span> <span class="token number">0x1edad891</span><span class="token punctuation">,</span> <span class="token number">0xce6279cf</span><span class="token punctuation">,</span> <span class="token number">0xcd3e7e6f</span><span class="token punctuation">,</span>
		<span class="token number">0x1618b166</span><span class="token punctuation">,</span> <span class="token number">0xfd2c1d05</span><span class="token punctuation">,</span> <span class="token number">0x848fd2c5</span><span class="token punctuation">,</span> <span class="token number">0xf6fb2299</span><span class="token punctuation">,</span>
		<span class="token number">0xf523f357</span><span class="token punctuation">,</span> <span class="token number">0xa6327623</span><span class="token punctuation">,</span> <span class="token number">0x93a83531</span><span class="token punctuation">,</span> <span class="token number">0x56cccd02</span><span class="token punctuation">,</span>
		<span class="token number">0xacf08162</span><span class="token punctuation">,</span> <span class="token number">0x5a75ebb5</span><span class="token punctuation">,</span> <span class="token number">0x6e163697</span><span class="token punctuation">,</span> <span class="token number">0x88d273cc</span><span class="token punctuation">,</span>
		<span class="token number">0xde966292</span><span class="token punctuation">,</span> <span class="token number">0x81b949d0</span><span class="token punctuation">,</span> <span class="token number">0x4c50901b</span><span class="token punctuation">,</span> <span class="token number">0x71c65614</span><span class="token punctuation">,</span>
		<span class="token number">0xe6c6c7bd</span><span class="token punctuation">,</span> <span class="token number">0x327a140a</span><span class="token punctuation">,</span> <span class="token number">0x45e1d006</span><span class="token punctuation">,</span> <span class="token number">0xc3f27b9a</span><span class="token punctuation">,</span>
		<span class="token number">0xc9aa53fd</span><span class="token punctuation">,</span> <span class="token number">0x62a80f00</span><span class="token punctuation">,</span> <span class="token number">0xbb25bfe2</span><span class="token punctuation">,</span> <span class="token number">0x35bdd2f6</span><span class="token punctuation">,</span>
		<span class="token number">0x71126905</span><span class="token punctuation">,</span> <span class="token number">0xb2040222</span><span class="token punctuation">,</span> <span class="token number">0xb6cbcf7c</span><span class="token punctuation">,</span> <span class="token number">0xcd769c2b</span><span class="token punctuation">,</span>
		<span class="token number">0x53113ec0</span><span class="token punctuation">,</span> <span class="token number">0x1640e3d3</span><span class="token punctuation">,</span> <span class="token number">0x38abbd60</span><span class="token punctuation">,</span> <span class="token number">0x2547adf0</span><span class="token punctuation">,</span>
		<span class="token number">0xba38209c</span><span class="token punctuation">,</span> <span class="token number">0xf746ce76</span><span class="token punctuation">,</span> <span class="token number">0x77afa1c5</span><span class="token punctuation">,</span> <span class="token number">0x20756060</span><span class="token punctuation">,</span>
		<span class="token number">0x85cbfe4e</span><span class="token punctuation">,</span> <span class="token number">0x8ae88dd8</span><span class="token punctuation">,</span> <span class="token number">0x7aaaf9b0</span><span class="token punctuation">,</span> <span class="token number">0x4cf9aa7e</span><span class="token punctuation">,</span>
		<span class="token number">0x1948c25c</span><span class="token punctuation">,</span> <span class="token number">0x02fb8a8c</span><span class="token punctuation">,</span> <span class="token number">0x01c36ae4</span><span class="token punctuation">,</span> <span class="token number">0xd6ebe1f9</span><span class="token punctuation">,</span>
		<span class="token number">0x90d4f869</span><span class="token punctuation">,</span> <span class="token number">0xa65cdea0</span><span class="token punctuation">,</span> <span class="token number">0x3f09252d</span><span class="token punctuation">,</span> <span class="token number">0xc208e69f</span><span class="token punctuation">,</span>
		<span class="token number">0xb74e6132</span><span class="token punctuation">,</span> <span class="token number">0xce77e25b</span><span class="token punctuation">,</span> <span class="token number">0x578fdfe3</span><span class="token punctuation">,</span> <span class="token number">0x3ac372e6</span>
	<span class="token punctuation">}</span><span class="token punctuation">;</span>

	<span class="token comment">// bcrypt IV: "OrpheanBeholderScryDoubt". The C implementation calls</span>
	<span class="token comment">// this "ciphertext", but it is really plaintext or an IV. We keep</span>
	<span class="token comment">// the name to make code comparison easier.</span>
	<span class="token keyword">static</span> <span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token keyword">int</span> bf_crypt_ciphertext<span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
		<span class="token number">0x4f727068</span><span class="token punctuation">,</span> <span class="token number">0x65616e42</span><span class="token punctuation">,</span> <span class="token number">0x65686f6c</span><span class="token punctuation">,</span>
		<span class="token number">0x64657253</span><span class="token punctuation">,</span> <span class="token number">0x63727944</span><span class="token punctuation">,</span> <span class="token number">0x6f756274</span>
	<span class="token punctuation">}</span><span class="token punctuation">;</span>

	<span class="token comment">// Table for Base64 encoding</span>
	<span class="token keyword">static</span> <span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token keyword">char</span> base64_code<span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
		<span class="token char">'.'</span><span class="token punctuation">,</span> <span class="token char">'/'</span><span class="token punctuation">,</span> <span class="token char">'A'</span><span class="token punctuation">,</span> <span class="token char">'B'</span><span class="token punctuation">,</span> <span class="token char">'C'</span><span class="token punctuation">,</span> <span class="token char">'D'</span><span class="token punctuation">,</span> <span class="token char">'E'</span><span class="token punctuation">,</span> <span class="token char">'F'</span><span class="token punctuation">,</span> <span class="token char">'G'</span><span class="token punctuation">,</span> <span class="token char">'H'</span><span class="token punctuation">,</span> <span class="token char">'I'</span><span class="token punctuation">,</span> <span class="token char">'J'</span><span class="token punctuation">,</span>
		<span class="token char">'K'</span><span class="token punctuation">,</span> <span class="token char">'L'</span><span class="token punctuation">,</span> <span class="token char">'M'</span><span class="token punctuation">,</span> <span class="token char">'N'</span><span class="token punctuation">,</span> <span class="token char">'O'</span><span class="token punctuation">,</span> <span class="token char">'P'</span><span class="token punctuation">,</span> <span class="token char">'Q'</span><span class="token punctuation">,</span> <span class="token char">'R'</span><span class="token punctuation">,</span> <span class="token char">'S'</span><span class="token punctuation">,</span> <span class="token char">'T'</span><span class="token punctuation">,</span> <span class="token char">'U'</span><span class="token punctuation">,</span> <span class="token char">'V'</span><span class="token punctuation">,</span>
		<span class="token char">'W'</span><span class="token punctuation">,</span> <span class="token char">'X'</span><span class="token punctuation">,</span> <span class="token char">'Y'</span><span class="token punctuation">,</span> <span class="token char">'Z'</span><span class="token punctuation">,</span> <span class="token char">'a'</span><span class="token punctuation">,</span> <span class="token char">'b'</span><span class="token punctuation">,</span> <span class="token char">'c'</span><span class="token punctuation">,</span> <span class="token char">'d'</span><span class="token punctuation">,</span> <span class="token char">'e'</span><span class="token punctuation">,</span> <span class="token char">'f'</span><span class="token punctuation">,</span> <span class="token char">'g'</span><span class="token punctuation">,</span> <span class="token char">'h'</span><span class="token punctuation">,</span>
		<span class="token char">'i'</span><span class="token punctuation">,</span> <span class="token char">'j'</span><span class="token punctuation">,</span> <span class="token char">'k'</span><span class="token punctuation">,</span> <span class="token char">'l'</span><span class="token punctuation">,</span> <span class="token char">'m'</span><span class="token punctuation">,</span> <span class="token char">'n'</span><span class="token punctuation">,</span> <span class="token char">'o'</span><span class="token punctuation">,</span> <span class="token char">'p'</span><span class="token punctuation">,</span> <span class="token char">'q'</span><span class="token punctuation">,</span> <span class="token char">'r'</span><span class="token punctuation">,</span> <span class="token char">'s'</span><span class="token punctuation">,</span> <span class="token char">'t'</span><span class="token punctuation">,</span>
		<span class="token char">'u'</span><span class="token punctuation">,</span> <span class="token char">'v'</span><span class="token punctuation">,</span> <span class="token char">'w'</span><span class="token punctuation">,</span> <span class="token char">'x'</span><span class="token punctuation">,</span> <span class="token char">'y'</span><span class="token punctuation">,</span> <span class="token char">'z'</span><span class="token punctuation">,</span> <span class="token char">'0'</span><span class="token punctuation">,</span> <span class="token char">'1'</span><span class="token punctuation">,</span> <span class="token char">'2'</span><span class="token punctuation">,</span> <span class="token char">'3'</span><span class="token punctuation">,</span> <span class="token char">'4'</span><span class="token punctuation">,</span> <span class="token char">'5'</span><span class="token punctuation">,</span>
		<span class="token char">'6'</span><span class="token punctuation">,</span> <span class="token char">'7'</span><span class="token punctuation">,</span> <span class="token char">'8'</span><span class="token punctuation">,</span> <span class="token char">'9'</span>
	<span class="token punctuation">}</span><span class="token punctuation">;</span>

	<span class="token comment">// Table for Base64 decoding</span>
	<span class="token keyword">static</span> <span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token keyword">byte</span> index_64<span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
		<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span>
		<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span>
		<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span>
		<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span>
		<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">54</span><span class="token punctuation">,</span> <span class="token number">55</span><span class="token punctuation">,</span>
		<span class="token number">56</span><span class="token punctuation">,</span> <span class="token number">57</span><span class="token punctuation">,</span> <span class="token number">58</span><span class="token punctuation">,</span> <span class="token number">59</span><span class="token punctuation">,</span> <span class="token number">60</span><span class="token punctuation">,</span> <span class="token number">61</span><span class="token punctuation">,</span> <span class="token number">62</span><span class="token punctuation">,</span> <span class="token number">63</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span>
		<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">,</span>
		<span class="token number">7</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">,</span> <span class="token number">9</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">11</span><span class="token punctuation">,</span> <span class="token number">12</span><span class="token punctuation">,</span> <span class="token number">13</span><span class="token punctuation">,</span> <span class="token number">14</span><span class="token punctuation">,</span> <span class="token number">15</span><span class="token punctuation">,</span> <span class="token number">16</span><span class="token punctuation">,</span>
		<span class="token number">17</span><span class="token punctuation">,</span> <span class="token number">18</span><span class="token punctuation">,</span> <span class="token number">19</span><span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">,</span> <span class="token number">21</span><span class="token punctuation">,</span> <span class="token number">22</span><span class="token punctuation">,</span> <span class="token number">23</span><span class="token punctuation">,</span> <span class="token number">24</span><span class="token punctuation">,</span> <span class="token number">25</span><span class="token punctuation">,</span> <span class="token number">26</span><span class="token punctuation">,</span> <span class="token number">27</span><span class="token punctuation">,</span>
		<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">28</span><span class="token punctuation">,</span> <span class="token number">29</span><span class="token punctuation">,</span> <span class="token number">30</span><span class="token punctuation">,</span>
		<span class="token number">31</span><span class="token punctuation">,</span> <span class="token number">32</span><span class="token punctuation">,</span> <span class="token number">33</span><span class="token punctuation">,</span> <span class="token number">34</span><span class="token punctuation">,</span> <span class="token number">35</span><span class="token punctuation">,</span> <span class="token number">36</span><span class="token punctuation">,</span> <span class="token number">37</span><span class="token punctuation">,</span> <span class="token number">38</span><span class="token punctuation">,</span> <span class="token number">39</span><span class="token punctuation">,</span> <span class="token number">40</span><span class="token punctuation">,</span>
		<span class="token number">41</span><span class="token punctuation">,</span> <span class="token number">42</span><span class="token punctuation">,</span> <span class="token number">43</span><span class="token punctuation">,</span> <span class="token number">44</span><span class="token punctuation">,</span> <span class="token number">45</span><span class="token punctuation">,</span> <span class="token number">46</span><span class="token punctuation">,</span> <span class="token number">47</span><span class="token punctuation">,</span> <span class="token number">48</span><span class="token punctuation">,</span> <span class="token number">49</span><span class="token punctuation">,</span> <span class="token number">50</span><span class="token punctuation">,</span>
		<span class="token number">51</span><span class="token punctuation">,</span> <span class="token number">52</span><span class="token punctuation">,</span> <span class="token number">53</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span>
	<span class="token punctuation">}</span><span class="token punctuation">;</span>

	<span class="token comment">// Expanded Blowfish key</span>
	<span class="token keyword">private</span> <span class="token keyword">int</span> <span class="token class-name">P</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
	<span class="token keyword">private</span> <span class="token keyword">int</span> <span class="token class-name">S</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

	<span class="token doc-comment comment">/**
	 * Encode a byte array using bcrypt's slightly-modified base64
	 * encoding scheme. Note that this is *not* compatible with
	 * the standard MIME-base64 encoding.
	 *
	 * <span class="token keyword">@param</span> <span class="token parameter">d</span>	the byte array to encode
	 * <span class="token keyword">@param</span> <span class="token parameter">len</span>	the number of bytes to encode
	 * <span class="token keyword">@return</span>	base64-encoded string
	 * <span class="token keyword">@exception</span> <span class="token reference"><span class="token class-name">IllegalArgumentException</span></span> if the length is invalid
	 */</span>
	<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token class-name">String</span> <span class="token function">encode_base64</span><span class="token punctuation">(</span><span class="token keyword">byte</span> d<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token keyword">int</span> len<span class="token punctuation">)</span>
		<span class="token keyword">throws</span> <span class="token class-name">IllegalArgumentException</span> <span class="token punctuation">{</span>
		<span class="token keyword">int</span> off <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
		<span class="token class-name">StringBuffer</span> rs <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StringBuffer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">int</span> c1<span class="token punctuation">,</span> c2<span class="token punctuation">;</span>

		<span class="token keyword">if</span> <span class="token punctuation">(</span>len <span class="token operator">&lt;=</span> <span class="token number">0</span> <span class="token operator">||</span> len <span class="token operator">></span> d<span class="token punctuation">.</span>length<span class="token punctuation">)</span>
			<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IllegalArgumentException</span> <span class="token punctuation">(</span><span class="token string">"Invalid len"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

		<span class="token keyword">while</span> <span class="token punctuation">(</span>off <span class="token operator">&lt;</span> len<span class="token punctuation">)</span> <span class="token punctuation">{</span>
			c1 <span class="token operator">=</span> d<span class="token punctuation">[</span>off<span class="token operator">++</span><span class="token punctuation">]</span> <span class="token operator">&amp;</span> <span class="token number">0xff</span><span class="token punctuation">;</span>
			rs<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>base64_code<span class="token punctuation">[</span><span class="token punctuation">(</span>c1 <span class="token operator">>></span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span> <span class="token number">0x3f</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			c1 <span class="token operator">=</span> <span class="token punctuation">(</span>c1 <span class="token operator">&amp;</span> <span class="token number">0x03</span><span class="token punctuation">)</span> <span class="token operator">&lt;&lt;</span> <span class="token number">4</span><span class="token punctuation">;</span>
			<span class="token keyword">if</span> <span class="token punctuation">(</span>off <span class="token operator">>=</span> len<span class="token punctuation">)</span> <span class="token punctuation">{</span>
				rs<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>base64_code<span class="token punctuation">[</span>c1 <span class="token operator">&amp;</span> <span class="token number">0x3f</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
				<span class="token keyword">break</span><span class="token punctuation">;</span>
			<span class="token punctuation">}</span>
			c2 <span class="token operator">=</span> d<span class="token punctuation">[</span>off<span class="token operator">++</span><span class="token punctuation">]</span> <span class="token operator">&amp;</span> <span class="token number">0xff</span><span class="token punctuation">;</span>
			c1 <span class="token operator">|=</span> <span class="token punctuation">(</span>c2 <span class="token operator">>></span> <span class="token number">4</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span> <span class="token number">0x0f</span><span class="token punctuation">;</span>
			rs<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>base64_code<span class="token punctuation">[</span>c1 <span class="token operator">&amp;</span> <span class="token number">0x3f</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			c1 <span class="token operator">=</span> <span class="token punctuation">(</span>c2 <span class="token operator">&amp;</span> <span class="token number">0x0f</span><span class="token punctuation">)</span> <span class="token operator">&lt;&lt;</span> <span class="token number">2</span><span class="token punctuation">;</span>
			<span class="token keyword">if</span> <span class="token punctuation">(</span>off <span class="token operator">>=</span> len<span class="token punctuation">)</span> <span class="token punctuation">{</span>
				rs<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>base64_code<span class="token punctuation">[</span>c1 <span class="token operator">&amp;</span> <span class="token number">0x3f</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
				<span class="token keyword">break</span><span class="token punctuation">;</span>
			<span class="token punctuation">}</span>
			c2 <span class="token operator">=</span> d<span class="token punctuation">[</span>off<span class="token operator">++</span><span class="token punctuation">]</span> <span class="token operator">&amp;</span> <span class="token number">0xff</span><span class="token punctuation">;</span>
			c1 <span class="token operator">|=</span> <span class="token punctuation">(</span>c2 <span class="token operator">>></span> <span class="token number">6</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span> <span class="token number">0x03</span><span class="token punctuation">;</span>
			rs<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>base64_code<span class="token punctuation">[</span>c1 <span class="token operator">&amp;</span> <span class="token number">0x3f</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			rs<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>base64_code<span class="token punctuation">[</span>c2 <span class="token operator">&amp;</span> <span class="token number">0x3f</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
		<span class="token keyword">return</span> rs<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>

	<span class="token doc-comment comment">/**
	 * Look up the 3 bits base64-encoded by the specified character,
	 * range-checking againt conversion table
	 * <span class="token keyword">@param</span> <span class="token parameter">x</span>	the base64-encoded value
	 * <span class="token keyword">@return</span>	the decoded value of x
	 */</span>
	<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">byte</span> <span class="token function">char64</span><span class="token punctuation">(</span><span class="token keyword">char</span> x<span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">)</span>x <span class="token operator">&lt;</span> <span class="token number">0</span> <span class="token operator">||</span> <span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">)</span>x <span class="token operator">></span> index_64<span class="token punctuation">.</span>length<span class="token punctuation">)</span>
			<span class="token keyword">return</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span>
		<span class="token keyword">return</span> index_64<span class="token punctuation">[</span><span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">)</span>x<span class="token punctuation">]</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>

	<span class="token doc-comment comment">/**
	 * Decode a string encoded using bcrypt's base64 scheme to a
	 * byte array. Note that this is *not* compatible with
	 * the standard MIME-base64 encoding.
	 * <span class="token keyword">@param</span> <span class="token parameter">s</span>	the string to decode
	 * <span class="token keyword">@param</span> <span class="token parameter">maxolen</span>	the maximum number of bytes to decode
	 * <span class="token keyword">@return</span>	an array containing the decoded bytes
	 * <span class="token keyword">@throws</span> <span class="token reference"><span class="token class-name">IllegalArgumentException</span></span> if maxolen is invalid
	 */</span>
	<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token function">decode_base64</span><span class="token punctuation">(</span><span class="token class-name">String</span> s<span class="token punctuation">,</span> <span class="token keyword">int</span> maxolen<span class="token punctuation">)</span>
		<span class="token keyword">throws</span> <span class="token class-name">IllegalArgumentException</span> <span class="token punctuation">{</span>
		<span class="token class-name">StringBuffer</span> rs <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StringBuffer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">int</span> off <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">,</span> slen <span class="token operator">=</span> s<span class="token punctuation">.</span><span class="token function">length</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> olen <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
		<span class="token keyword">byte</span> ret<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
		<span class="token keyword">byte</span> c1<span class="token punctuation">,</span> c2<span class="token punctuation">,</span> c3<span class="token punctuation">,</span> c4<span class="token punctuation">,</span> o<span class="token punctuation">;</span>

		<span class="token keyword">if</span> <span class="token punctuation">(</span>maxolen <span class="token operator">&lt;=</span> <span class="token number">0</span><span class="token punctuation">)</span>
			<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IllegalArgumentException</span> <span class="token punctuation">(</span><span class="token string">"Invalid maxolen"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

		<span class="token keyword">while</span> <span class="token punctuation">(</span>off <span class="token operator">&lt;</span> slen <span class="token operator">-</span> <span class="token number">1</span> <span class="token operator">&amp;&amp;</span> olen <span class="token operator">&lt;</span> maxolen<span class="token punctuation">)</span> <span class="token punctuation">{</span>
			c1 <span class="token operator">=</span> <span class="token function">char64</span><span class="token punctuation">(</span>s<span class="token punctuation">.</span><span class="token function">charAt</span><span class="token punctuation">(</span>off<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			c2 <span class="token operator">=</span> <span class="token function">char64</span><span class="token punctuation">(</span>s<span class="token punctuation">.</span><span class="token function">charAt</span><span class="token punctuation">(</span>off<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token keyword">if</span> <span class="token punctuation">(</span>c1 <span class="token operator">==</span> <span class="token operator">-</span><span class="token number">1</span> <span class="token operator">||</span> c2 <span class="token operator">==</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span>
				<span class="token keyword">break</span><span class="token punctuation">;</span>
			o <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">byte</span><span class="token punctuation">)</span><span class="token punctuation">(</span>c1 <span class="token operator">&lt;&lt;</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			o <span class="token operator">|=</span> <span class="token punctuation">(</span>c2 <span class="token operator">&amp;</span> <span class="token number">0x30</span><span class="token punctuation">)</span> <span class="token operator">>></span> <span class="token number">4</span><span class="token punctuation">;</span>
			rs<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token keyword">char</span><span class="token punctuation">)</span>o<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">++</span>olen <span class="token operator">>=</span> maxolen <span class="token operator">||</span> off <span class="token operator">>=</span> slen<span class="token punctuation">)</span>
				<span class="token keyword">break</span><span class="token punctuation">;</span>
			c3 <span class="token operator">=</span> <span class="token function">char64</span><span class="token punctuation">(</span>s<span class="token punctuation">.</span><span class="token function">charAt</span><span class="token punctuation">(</span>off<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token keyword">if</span> <span class="token punctuation">(</span>c3 <span class="token operator">==</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span>
				<span class="token keyword">break</span><span class="token punctuation">;</span>
			o <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">byte</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">(</span>c2 <span class="token operator">&amp;</span> <span class="token number">0x0f</span><span class="token punctuation">)</span> <span class="token operator">&lt;&lt;</span> <span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			o <span class="token operator">|=</span> <span class="token punctuation">(</span>c3 <span class="token operator">&amp;</span> <span class="token number">0x3c</span><span class="token punctuation">)</span> <span class="token operator">>></span> <span class="token number">2</span><span class="token punctuation">;</span>
			rs<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token keyword">char</span><span class="token punctuation">)</span>o<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">++</span>olen <span class="token operator">>=</span> maxolen <span class="token operator">||</span> off <span class="token operator">>=</span> slen<span class="token punctuation">)</span>
				<span class="token keyword">break</span><span class="token punctuation">;</span>
			c4 <span class="token operator">=</span> <span class="token function">char64</span><span class="token punctuation">(</span>s<span class="token punctuation">.</span><span class="token function">charAt</span><span class="token punctuation">(</span>off<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			o <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">byte</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">(</span>c3 <span class="token operator">&amp;</span> <span class="token number">0x03</span><span class="token punctuation">)</span> <span class="token operator">&lt;&lt;</span> <span class="token number">6</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			o <span class="token operator">|=</span> c4<span class="token punctuation">;</span>
			rs<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token keyword">char</span><span class="token punctuation">)</span>o<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token operator">++</span>olen<span class="token punctuation">;</span>
		<span class="token punctuation">}</span>

		ret <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token keyword">byte</span><span class="token punctuation">[</span>olen<span class="token punctuation">]</span><span class="token punctuation">;</span>
		<span class="token keyword">for</span> <span class="token punctuation">(</span>off <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> off <span class="token operator">&lt;</span> olen<span class="token punctuation">;</span> off<span class="token operator">++</span><span class="token punctuation">)</span>
			ret<span class="token punctuation">[</span>off<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">byte</span><span class="token punctuation">)</span>rs<span class="token punctuation">.</span><span class="token function">charAt</span><span class="token punctuation">(</span>off<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">return</span> ret<span class="token punctuation">;</span>
	<span class="token punctuation">}</span>

	<span class="token doc-comment comment">/**
	 * Blowfish encipher a single 64-bit block encoded as
	 * two 32-bit halves
	 * <span class="token keyword">@param</span> <span class="token parameter">lr</span>	an array containing the two 32-bit half blocks
	 * <span class="token keyword">@param</span> <span class="token parameter">off</span>	the position in the array of the blocks
	 */</span>
	<span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token keyword">void</span> <span class="token function">encipher</span><span class="token punctuation">(</span><span class="token keyword">int</span> lr<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token keyword">int</span> off<span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token keyword">int</span> i<span class="token punctuation">,</span> n<span class="token punctuation">,</span> l <span class="token operator">=</span> lr<span class="token punctuation">[</span>off<span class="token punctuation">]</span><span class="token punctuation">,</span> r <span class="token operator">=</span> lr<span class="token punctuation">[</span>off <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

		l <span class="token operator">^=</span> <span class="token class-name">P</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
		<span class="token keyword">for</span> <span class="token punctuation">(</span>i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;=</span> BLOWFISH_NUM_ROUNDS <span class="token operator">-</span> <span class="token number">2</span><span class="token punctuation">;</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
			<span class="token comment">// Feistel substitution on left word</span>
			n <span class="token operator">=</span> <span class="token class-name">S</span><span class="token punctuation">[</span><span class="token punctuation">(</span>l <span class="token operator">>></span> <span class="token number">24</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span> <span class="token number">0xff</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
			n <span class="token operator">+=</span> <span class="token class-name">S</span><span class="token punctuation">[</span><span class="token number">0x100</span> <span class="token operator">|</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>l <span class="token operator">>></span> <span class="token number">16</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span> <span class="token number">0xff</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
			n <span class="token operator">^=</span> <span class="token class-name">S</span><span class="token punctuation">[</span><span class="token number">0x200</span> <span class="token operator">|</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>l <span class="token operator">>></span> <span class="token number">8</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span> <span class="token number">0xff</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
			n <span class="token operator">+=</span> <span class="token class-name">S</span><span class="token punctuation">[</span><span class="token number">0x300</span> <span class="token operator">|</span> <span class="token punctuation">(</span>l <span class="token operator">&amp;</span> <span class="token number">0xff</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
			r <span class="token operator">^=</span> n <span class="token operator">^</span> <span class="token class-name">P</span><span class="token punctuation">[</span><span class="token operator">++</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span>

			<span class="token comment">// Feistel substitution on right word</span>
			n <span class="token operator">=</span> <span class="token class-name">S</span><span class="token punctuation">[</span><span class="token punctuation">(</span>r <span class="token operator">>></span> <span class="token number">24</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span> <span class="token number">0xff</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
			n <span class="token operator">+=</span> <span class="token class-name">S</span><span class="token punctuation">[</span><span class="token number">0x100</span> <span class="token operator">|</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>r <span class="token operator">>></span> <span class="token number">16</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span> <span class="token number">0xff</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
			n <span class="token operator">^=</span> <span class="token class-name">S</span><span class="token punctuation">[</span><span class="token number">0x200</span> <span class="token operator">|</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>r <span class="token operator">>></span> <span class="token number">8</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span> <span class="token number">0xff</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
			n <span class="token operator">+=</span> <span class="token class-name">S</span><span class="token punctuation">[</span><span class="token number">0x300</span> <span class="token operator">|</span> <span class="token punctuation">(</span>r <span class="token operator">&amp;</span> <span class="token number">0xff</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
			l <span class="token operator">^=</span> n <span class="token operator">^</span> <span class="token class-name">P</span><span class="token punctuation">[</span><span class="token operator">++</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
		lr<span class="token punctuation">[</span>off<span class="token punctuation">]</span> <span class="token operator">=</span> r <span class="token operator">^</span> <span class="token class-name">P</span><span class="token punctuation">[</span>BLOWFISH_NUM_ROUNDS <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
		lr<span class="token punctuation">[</span>off <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">=</span> l<span class="token punctuation">;</span>
	<span class="token punctuation">}</span>

	<span class="token doc-comment comment">/**
	 * Cycically extract a word of key material
	 * <span class="token keyword">@param</span> <span class="token parameter">data</span>	the string to extract the data from
	 * <span class="token keyword">@param</span> <span class="token parameter">offp</span>	a "pointer" (as a one-entry array) to the
	 * current offset into data
	 * <span class="token keyword">@return</span>	the next word of material from data
	 */</span>
	<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">int</span> <span class="token function">streamtoword</span><span class="token punctuation">(</span><span class="token keyword">byte</span> data<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token keyword">int</span> offp<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token keyword">int</span> i<span class="token punctuation">;</span>
		<span class="token keyword">int</span> word <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
		<span class="token keyword">int</span> off <span class="token operator">=</span> offp<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

		<span class="token keyword">for</span> <span class="token punctuation">(</span>i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token number">4</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
			word <span class="token operator">=</span> <span class="token punctuation">(</span>word <span class="token operator">&lt;&lt;</span> <span class="token number">8</span><span class="token punctuation">)</span> <span class="token operator">|</span> <span class="token punctuation">(</span>data<span class="token punctuation">[</span>off<span class="token punctuation">]</span> <span class="token operator">&amp;</span> <span class="token number">0xff</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			off <span class="token operator">=</span> <span class="token punctuation">(</span>off <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">%</span> data<span class="token punctuation">.</span>length<span class="token punctuation">;</span>
		<span class="token punctuation">}</span>

		offp<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">=</span> off<span class="token punctuation">;</span>
		<span class="token keyword">return</span> word<span class="token punctuation">;</span>
	<span class="token punctuation">}</span>

	<span class="token doc-comment comment">/**
	 * Initialise the Blowfish key schedule
	 */</span>
	<span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">init_key</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token class-name">P</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token class-name">P_orig</span><span class="token punctuation">.</span><span class="token function">clone</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token class-name">S</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token class-name">S_orig</span><span class="token punctuation">.</span><span class="token function">clone</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>

	<span class="token doc-comment comment">/**
	 * Key the Blowfish cipher
	 * <span class="token keyword">@param</span> <span class="token parameter">key</span>	an array containing the key
	 */</span>
	<span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">key</span><span class="token punctuation">(</span><span class="token keyword">byte</span> key<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token keyword">int</span> i<span class="token punctuation">;</span>
		<span class="token keyword">int</span> koffp<span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token number">0</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
		<span class="token keyword">int</span> lr<span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
		<span class="token keyword">int</span> plen <span class="token operator">=</span> <span class="token class-name">P</span><span class="token punctuation">.</span>length<span class="token punctuation">,</span> slen <span class="token operator">=</span> <span class="token class-name">S</span><span class="token punctuation">.</span>length<span class="token punctuation">;</span>

		<span class="token keyword">for</span> <span class="token punctuation">(</span>i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> plen<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span>
			<span class="token class-name">P</span><span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token class-name">P</span><span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">^</span> <span class="token function">streamtoword</span><span class="token punctuation">(</span>key<span class="token punctuation">,</span> koffp<span class="token punctuation">)</span><span class="token punctuation">;</span>

		<span class="token keyword">for</span> <span class="token punctuation">(</span>i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> plen<span class="token punctuation">;</span> i <span class="token operator">+=</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
			<span class="token function">encipher</span><span class="token punctuation">(</span>lr<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token class-name">P</span><span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> lr<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
			<span class="token class-name">P</span><span class="token punctuation">[</span>i <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">=</span> lr<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>

		<span class="token keyword">for</span> <span class="token punctuation">(</span>i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> slen<span class="token punctuation">;</span> i <span class="token operator">+=</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
			<span class="token function">encipher</span><span class="token punctuation">(</span>lr<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token class-name">S</span><span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> lr<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
			<span class="token class-name">S</span><span class="token punctuation">[</span>i <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">=</span> lr<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
	<span class="token punctuation">}</span>

	<span class="token doc-comment comment">/**
	 * Perform the "enhanced key schedule" step described by
	 * Provos and Mazieres in "A Future-Adaptable Password Scheme"
	 * http://www.openbsd.org/papers/bcrypt-paper.ps
	 * <span class="token keyword">@param</span> <span class="token parameter">data</span>	salt information
	 * <span class="token keyword">@param</span> <span class="token parameter">key</span>	password information
	 */</span>
	<span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">ekskey</span><span class="token punctuation">(</span><span class="token keyword">byte</span> data<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token keyword">byte</span> key<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token keyword">int</span> i<span class="token punctuation">;</span>
		<span class="token keyword">int</span> koffp<span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token number">0</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> doffp<span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token number">0</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
		<span class="token keyword">int</span> lr<span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
		<span class="token keyword">int</span> plen <span class="token operator">=</span> <span class="token class-name">P</span><span class="token punctuation">.</span>length<span class="token punctuation">,</span> slen <span class="token operator">=</span> <span class="token class-name">S</span><span class="token punctuation">.</span>length<span class="token punctuation">;</span>

		<span class="token keyword">for</span> <span class="token punctuation">(</span>i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> plen<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span>
			<span class="token class-name">P</span><span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token class-name">P</span><span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">^</span> <span class="token function">streamtoword</span><span class="token punctuation">(</span>key<span class="token punctuation">,</span> koffp<span class="token punctuation">)</span><span class="token punctuation">;</span>

		<span class="token keyword">for</span> <span class="token punctuation">(</span>i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> plen<span class="token punctuation">;</span> i <span class="token operator">+=</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
			lr<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">^=</span> <span class="token function">streamtoword</span><span class="token punctuation">(</span>data<span class="token punctuation">,</span> doffp<span class="token punctuation">)</span><span class="token punctuation">;</span>
			lr<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">^=</span> <span class="token function">streamtoword</span><span class="token punctuation">(</span>data<span class="token punctuation">,</span> doffp<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token function">encipher</span><span class="token punctuation">(</span>lr<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token class-name">P</span><span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> lr<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
			<span class="token class-name">P</span><span class="token punctuation">[</span>i <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">=</span> lr<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>

		<span class="token keyword">for</span> <span class="token punctuation">(</span>i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> slen<span class="token punctuation">;</span> i <span class="token operator">+=</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
			lr<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">^=</span> <span class="token function">streamtoword</span><span class="token punctuation">(</span>data<span class="token punctuation">,</span> doffp<span class="token punctuation">)</span><span class="token punctuation">;</span>
			lr<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">^=</span> <span class="token function">streamtoword</span><span class="token punctuation">(</span>data<span class="token punctuation">,</span> doffp<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token function">encipher</span><span class="token punctuation">(</span>lr<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token class-name">S</span><span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> lr<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
			<span class="token class-name">S</span><span class="token punctuation">[</span>i <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">=</span> lr<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
	<span class="token punctuation">}</span>

	<span class="token doc-comment comment">/**
	 * Perform the central password hashing step in the
	 * bcrypt scheme
	 * <span class="token keyword">@param</span> <span class="token parameter">password</span>	the password to hash
	 * <span class="token keyword">@param</span> <span class="token parameter">salt</span>	the binary salt to hash with the password
	 * <span class="token keyword">@param</span> <span class="token parameter">log_rounds</span>	the binary logarithm of the number
	 * of rounds of hashing to apply
	 * <span class="token keyword">@param</span> <span class="token parameter">cdata</span>         the plaintext to encrypt
	 * <span class="token keyword">@return</span>	an array containing the binary hashed password
	 */</span>
	<span class="token keyword">public</span> <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token function">crypt_raw</span><span class="token punctuation">(</span><span class="token keyword">byte</span> password<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token keyword">byte</span> salt<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token keyword">int</span> log_rounds<span class="token punctuation">,</span>
	    <span class="token keyword">int</span> cdata<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token keyword">int</span> rounds<span class="token punctuation">,</span> i<span class="token punctuation">,</span> j<span class="token punctuation">;</span>
		<span class="token keyword">int</span> clen <span class="token operator">=</span> cdata<span class="token punctuation">.</span>length<span class="token punctuation">;</span>
		<span class="token keyword">byte</span> ret<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

		<span class="token keyword">if</span> <span class="token punctuation">(</span>log_rounds <span class="token operator">&lt;</span> <span class="token number">4</span> <span class="token operator">||</span> log_rounds <span class="token operator">></span> <span class="token number">30</span><span class="token punctuation">)</span>
			<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IllegalArgumentException</span> <span class="token punctuation">(</span><span class="token string">"Bad number of rounds"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		rounds <span class="token operator">=</span> <span class="token number">1</span> <span class="token operator">&lt;&lt;</span> log_rounds<span class="token punctuation">;</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span>salt<span class="token punctuation">.</span>length <span class="token operator">!=</span> BCRYPT_SALT_LEN<span class="token punctuation">)</span>
			<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IllegalArgumentException</span> <span class="token punctuation">(</span><span class="token string">"Bad salt length"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

		<span class="token function">init_key</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token function">ekskey</span><span class="token punctuation">(</span>salt<span class="token punctuation">,</span> password<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">for</span> <span class="token punctuation">(</span>i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">!=</span> rounds<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
			<span class="token function">key</span><span class="token punctuation">(</span>password<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token function">key</span><span class="token punctuation">(</span>salt<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>

		<span class="token keyword">for</span> <span class="token punctuation">(</span>i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token number">64</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
			<span class="token keyword">for</span> <span class="token punctuation">(</span>j <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> j <span class="token operator">&lt;</span> <span class="token punctuation">(</span>clen <span class="token operator">>></span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> j<span class="token operator">++</span><span class="token punctuation">)</span>
				<span class="token function">encipher</span><span class="token punctuation">(</span>cdata<span class="token punctuation">,</span> j <span class="token operator">&lt;&lt;</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>

		ret <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token keyword">byte</span><span class="token punctuation">[</span>clen <span class="token operator">*</span> <span class="token number">4</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
		<span class="token keyword">for</span> <span class="token punctuation">(</span>i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">,</span> j <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> clen<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
			ret<span class="token punctuation">[</span>j<span class="token operator">++</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">byte</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">(</span>cdata<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">>></span> <span class="token number">24</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span> <span class="token number">0xff</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			ret<span class="token punctuation">[</span>j<span class="token operator">++</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">byte</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">(</span>cdata<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">>></span> <span class="token number">16</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span> <span class="token number">0xff</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			ret<span class="token punctuation">[</span>j<span class="token operator">++</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">byte</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">(</span>cdata<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">>></span> <span class="token number">8</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span> <span class="token number">0xff</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			ret<span class="token punctuation">[</span>j<span class="token operator">++</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">byte</span><span class="token punctuation">)</span><span class="token punctuation">(</span>cdata<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">&amp;</span> <span class="token number">0xff</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
		<span class="token keyword">return</span> ret<span class="token punctuation">;</span>
	<span class="token punctuation">}</span>

	<span class="token doc-comment comment">/**
	 * Hash a password using the OpenBSD bcrypt scheme
	 * <span class="token keyword">@param</span> <span class="token parameter">password</span>	the password to hash
	 * <span class="token keyword">@param</span> <span class="token parameter">salt</span>	the salt to hash with (perhaps generated
	 * using BCrypt.gensalt)
	 * <span class="token keyword">@return</span>	the hashed password
	 */</span>
	<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">String</span> <span class="token function">hashpw</span><span class="token punctuation">(</span><span class="token class-name">String</span> password<span class="token punctuation">,</span> <span class="token class-name">String</span> salt<span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token class-name">BCrypt</span> <span class="token class-name">B</span><span class="token punctuation">;</span>
		<span class="token class-name">String</span> real_salt<span class="token punctuation">;</span>
		<span class="token keyword">byte</span> passwordb<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> saltb<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> hashed<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
		<span class="token keyword">char</span> minor <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">char</span><span class="token punctuation">)</span><span class="token number">0</span><span class="token punctuation">;</span>
		<span class="token keyword">int</span> rounds<span class="token punctuation">,</span> off <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
		<span class="token class-name">StringBuffer</span> rs <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StringBuffer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

		<span class="token keyword">if</span> <span class="token punctuation">(</span>salt<span class="token punctuation">.</span><span class="token function">charAt</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token char">'$'</span> <span class="token operator">||</span> salt<span class="token punctuation">.</span><span class="token function">charAt</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token char">'2'</span><span class="token punctuation">)</span>
			<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IllegalArgumentException</span> <span class="token punctuation">(</span><span class="token string">"Invalid salt version"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span>salt<span class="token punctuation">.</span><span class="token function">charAt</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token char">'$'</span><span class="token punctuation">)</span>
			off <span class="token operator">=</span> <span class="token number">3</span><span class="token punctuation">;</span>
		<span class="token keyword">else</span> <span class="token punctuation">{</span>
			minor <span class="token operator">=</span> salt<span class="token punctuation">.</span><span class="token function">charAt</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token keyword">if</span> <span class="token punctuation">(</span>minor <span class="token operator">!=</span> <span class="token char">'a'</span> <span class="token operator">||</span> salt<span class="token punctuation">.</span><span class="token function">charAt</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token char">'$'</span><span class="token punctuation">)</span>
				<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IllegalArgumentException</span> <span class="token punctuation">(</span><span class="token string">"Invalid salt revision"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			off <span class="token operator">=</span> <span class="token number">4</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>

		<span class="token comment">// Extract number of rounds</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span>salt<span class="token punctuation">.</span><span class="token function">charAt</span><span class="token punctuation">(</span>off <span class="token operator">+</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token operator">></span> <span class="token char">'$'</span><span class="token punctuation">)</span>
			<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IllegalArgumentException</span> <span class="token punctuation">(</span><span class="token string">"Missing salt rounds"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		rounds <span class="token operator">=</span> <span class="token class-name">Integer</span><span class="token punctuation">.</span><span class="token function">parseInt</span><span class="token punctuation">(</span>salt<span class="token punctuation">.</span><span class="token function">substring</span><span class="token punctuation">(</span>off<span class="token punctuation">,</span> off <span class="token operator">+</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

		real_salt <span class="token operator">=</span> salt<span class="token punctuation">.</span><span class="token function">substring</span><span class="token punctuation">(</span>off <span class="token operator">+</span> <span class="token number">3</span><span class="token punctuation">,</span> off <span class="token operator">+</span> <span class="token number">25</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">try</span> <span class="token punctuation">{</span>
			passwordb <span class="token operator">=</span> <span class="token punctuation">(</span>password <span class="token operator">+</span> <span class="token punctuation">(</span>minor <span class="token operator">>=</span> <span class="token char">'a'</span> <span class="token operator">?</span> <span class="token string">"\000"</span> <span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getBytes</span><span class="token punctuation">(</span><span class="token string">"UTF-8"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">UnsupportedEncodingException</span> uee<span class="token punctuation">)</span> <span class="token punctuation">{</span>
			<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">AssertionError</span><span class="token punctuation">(</span><span class="token string">"UTF-8 is not supported"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>

		saltb <span class="token operator">=</span> <span class="token function">decode_base64</span><span class="token punctuation">(</span>real_salt<span class="token punctuation">,</span> BCRYPT_SALT_LEN<span class="token punctuation">)</span><span class="token punctuation">;</span>

		<span class="token class-name">B</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">BCrypt</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		hashed <span class="token operator">=</span> <span class="token class-name">B</span><span class="token punctuation">.</span><span class="token function">crypt_raw</span><span class="token punctuation">(</span>passwordb<span class="token punctuation">,</span> saltb<span class="token punctuation">,</span> rounds<span class="token punctuation">,</span>
		    <span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>bf_crypt_ciphertext<span class="token punctuation">.</span><span class="token function">clone</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

		rs<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">"$2"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span>minor <span class="token operator">>=</span> <span class="token char">'a'</span><span class="token punctuation">)</span>
			rs<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>minor<span class="token punctuation">)</span><span class="token punctuation">;</span>
		rs<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">"$"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span>rounds <span class="token operator">&lt;</span> <span class="token number">10</span><span class="token punctuation">)</span>
			rs<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">"0"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span>rounds <span class="token operator">></span> <span class="token number">30</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
			<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IllegalArgumentException</span><span class="token punctuation">(</span>
			    <span class="token string">"rounds exceeds maximum (30)"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
		rs<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token class-name">Integer</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span>rounds<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		rs<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">"$"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		rs<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token function">encode_base64</span><span class="token punctuation">(</span>saltb<span class="token punctuation">,</span> saltb<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		rs<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token function">encode_base64</span><span class="token punctuation">(</span>hashed<span class="token punctuation">,</span>
		    bf_crypt_ciphertext<span class="token punctuation">.</span>length <span class="token operator">*</span> <span class="token number">4</span> <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">return</span> rs<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>

	<span class="token doc-comment comment">/**
	 * Generate a salt for use with the BCrypt.hashpw() method
	 * <span class="token keyword">@param</span> <span class="token parameter">log_rounds</span>	the log2 of the number of rounds of
	 * hashing to apply - the work factor therefore increases as
	 * 2**log_rounds.
	 * <span class="token keyword">@param</span> <span class="token parameter">random</span>		an instance of SecureRandom to use
	 * <span class="token keyword">@return</span>	an encoded salt value
	 */</span>
	<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">String</span> <span class="token function">gensalt</span><span class="token punctuation">(</span><span class="token keyword">int</span> log_rounds<span class="token punctuation">,</span> <span class="token class-name">SecureRandom</span> random<span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token class-name">StringBuffer</span> rs <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StringBuffer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">byte</span> rnd<span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token keyword">byte</span><span class="token punctuation">[</span>BCRYPT_SALT_LEN<span class="token punctuation">]</span><span class="token punctuation">;</span>

		random<span class="token punctuation">.</span><span class="token function">nextBytes</span><span class="token punctuation">(</span>rnd<span class="token punctuation">)</span><span class="token punctuation">;</span>

		rs<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">"$2a$"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span>log_rounds <span class="token operator">&lt;</span> <span class="token number">10</span><span class="token punctuation">)</span>
			rs<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">"0"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span>log_rounds <span class="token operator">></span> <span class="token number">30</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
			<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IllegalArgumentException</span><span class="token punctuation">(</span>
			    <span class="token string">"log_rounds exceeds maximum (30)"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
		rs<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token class-name">Integer</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span>log_rounds<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		rs<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">"$"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		rs<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token function">encode_base64</span><span class="token punctuation">(</span>rnd<span class="token punctuation">,</span> rnd<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">return</span> rs<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>

	<span class="token doc-comment comment">/**
	 * Generate a salt for use with the BCrypt.hashpw() method
	 * <span class="token keyword">@param</span> <span class="token parameter">log_rounds</span>	the log2 of the number of rounds of
	 * hashing to apply - the work factor therefore increases as
	 * 2**log_rounds.
	 * <span class="token keyword">@return</span>	an encoded salt value
	 */</span>
	<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">String</span> <span class="token function">gensalt</span><span class="token punctuation">(</span><span class="token keyword">int</span> log_rounds<span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token keyword">return</span> <span class="token function">gensalt</span><span class="token punctuation">(</span>log_rounds<span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token class-name">SecureRandom</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>

	<span class="token doc-comment comment">/**
	 * Generate a salt for use with the BCrypt.hashpw() method,
	 * selecting a reasonable default for the number of hashing
	 * rounds to apply
	 * <span class="token keyword">@return</span>	an encoded salt value
	 */</span>
	<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">String</span> <span class="token function">gensalt</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token keyword">return</span> <span class="token function">gensalt</span><span class="token punctuation">(</span>GENSALT_DEFAULT_LOG2_ROUNDS<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>

	<span class="token doc-comment comment">/**
	 * Check that a plaintext password matches a previously hashed
	 * one
	 * <span class="token keyword">@param</span> <span class="token parameter">plaintext</span>	the plaintext password to verify
	 * <span class="token keyword">@param</span> <span class="token parameter">hashed</span>	the previously-hashed password
	 * <span class="token keyword">@return</span>	true if the passwords match, false otherwise
	 */</span>
	<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">boolean</span> <span class="token function">checkpw</span><span class="token punctuation">(</span><span class="token class-name">String</span> plaintext<span class="token punctuation">,</span> <span class="token class-name">String</span> hashed<span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token keyword">byte</span> hashed_bytes<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
		<span class="token keyword">byte</span> try_bytes<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
		<span class="token keyword">try</span> <span class="token punctuation">{</span>
			<span class="token class-name">String</span> try_pw <span class="token operator">=</span> <span class="token function">hashpw</span><span class="token punctuation">(</span>plaintext<span class="token punctuation">,</span> hashed<span class="token punctuation">)</span><span class="token punctuation">;</span>
			hashed_bytes <span class="token operator">=</span> hashed<span class="token punctuation">.</span><span class="token function">getBytes</span><span class="token punctuation">(</span><span class="token string">"UTF-8"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			try_bytes <span class="token operator">=</span> try_pw<span class="token punctuation">.</span><span class="token function">getBytes</span><span class="token punctuation">(</span><span class="token string">"UTF-8"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">UnsupportedEncodingException</span> uee<span class="token punctuation">)</span> <span class="token punctuation">{</span>
			<span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span>hashed_bytes<span class="token punctuation">.</span>length <span class="token operator">!=</span> try_bytes<span class="token punctuation">.</span>length<span class="token punctuation">)</span>
			<span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
		<span class="token keyword">byte</span> ret <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
		<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> try_bytes<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span>
			ret <span class="token operator">|=</span> hashed_bytes<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">^</span> try_bytes<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span>
		<span class="token keyword">return</span> ret <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
<span class="token punctuation">}</span>

</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br><span class="line-number">151</span><br><span class="line-number">152</span><br><span class="line-number">153</span><br><span class="line-number">154</span><br><span class="line-number">155</span><br><span class="line-number">156</span><br><span class="line-number">157</span><br><span class="line-number">158</span><br><span class="line-number">159</span><br><span class="line-number">160</span><br><span class="line-number">161</span><br><span class="line-number">162</span><br><span class="line-number">163</span><br><span class="line-number">164</span><br><span class="line-number">165</span><br><span class="line-number">166</span><br><span class="line-number">167</span><br><span class="line-number">168</span><br><span class="line-number">169</span><br><span class="line-number">170</span><br><span class="line-number">171</span><br><span class="line-number">172</span><br><span class="line-number">173</span><br><span class="line-number">174</span><br><span class="line-number">175</span><br><span class="line-number">176</span><br><span class="line-number">177</span><br><span class="line-number">178</span><br><span class="line-number">179</span><br><span class="line-number">180</span><br><span class="line-number">181</span><br><span class="line-number">182</span><br><span class="line-number">183</span><br><span class="line-number">184</span><br><span class="line-number">185</span><br><span class="line-number">186</span><br><span class="line-number">187</span><br><span class="line-number">188</span><br><span class="line-number">189</span><br><span class="line-number">190</span><br><span class="line-number">191</span><br><span class="line-number">192</span><br><span class="line-number">193</span><br><span class="line-number">194</span><br><span class="line-number">195</span><br><span class="line-number">196</span><br><span class="line-number">197</span><br><span class="line-number">198</span><br><span class="line-number">199</span><br><span class="line-number">200</span><br><span class="line-number">201</span><br><span class="line-number">202</span><br><span class="line-number">203</span><br><span class="line-number">204</span><br><span class="line-number">205</span><br><span class="line-number">206</span><br><span class="line-number">207</span><br><span class="line-number">208</span><br><span class="line-number">209</span><br><span class="line-number">210</span><br><span class="line-number">211</span><br><span class="line-number">212</span><br><span class="line-number">213</span><br><span class="line-number">214</span><br><span class="line-number">215</span><br><span class="line-number">216</span><br><span class="line-number">217</span><br><span class="line-number">218</span><br><span class="line-number">219</span><br><span class="line-number">220</span><br><span class="line-number">221</span><br><span class="line-number">222</span><br><span class="line-number">223</span><br><span class="line-number">224</span><br><span class="line-number">225</span><br><span class="line-number">226</span><br><span class="line-number">227</span><br><span class="line-number">228</span><br><span class="line-number">229</span><br><span class="line-number">230</span><br><span class="line-number">231</span><br><span class="line-number">232</span><br><span class="line-number">233</span><br><span class="line-number">234</span><br><span class="line-number">235</span><br><span class="line-number">236</span><br><span class="line-number">237</span><br><span class="line-number">238</span><br><span class="line-number">239</span><br><span class="line-number">240</span><br><span class="line-number">241</span><br><span class="line-number">242</span><br><span class="line-number">243</span><br><span class="line-number">244</span><br><span class="line-number">245</span><br><span class="line-number">246</span><br><span class="line-number">247</span><br><span class="line-number">248</span><br><span class="line-number">249</span><br><span class="line-number">250</span><br><span class="line-number">251</span><br><span class="line-number">252</span><br><span class="line-number">253</span><br><span class="line-number">254</span><br><span class="line-number">255</span><br><span class="line-number">256</span><br><span class="line-number">257</span><br><span class="line-number">258</span><br><span class="line-number">259</span><br><span class="line-number">260</span><br><span class="line-number">261</span><br><span class="line-number">262</span><br><span class="line-number">263</span><br><span class="line-number">264</span><br><span class="line-number">265</span><br><span class="line-number">266</span><br><span class="line-number">267</span><br><span class="line-number">268</span><br><span class="line-number">269</span><br><span class="line-number">270</span><br><span class="line-number">271</span><br><span class="line-number">272</span><br><span class="line-number">273</span><br><span class="line-number">274</span><br><span class="line-number">275</span><br><span class="line-number">276</span><br><span class="line-number">277</span><br><span class="line-number">278</span><br><span class="line-number">279</span><br><span class="line-number">280</span><br><span class="line-number">281</span><br><span class="line-number">282</span><br><span class="line-number">283</span><br><span class="line-number">284</span><br><span class="line-number">285</span><br><span class="line-number">286</span><br><span class="line-number">287</span><br><span class="line-number">288</span><br><span class="line-number">289</span><br><span class="line-number">290</span><br><span class="line-number">291</span><br><span class="line-number">292</span><br><span class="line-number">293</span><br><span class="line-number">294</span><br><span class="line-number">295</span><br><span class="line-number">296</span><br><span class="line-number">297</span><br><span class="line-number">298</span><br><span class="line-number">299</span><br><span class="line-number">300</span><br><span class="line-number">301</span><br><span class="line-number">302</span><br><span class="line-number">303</span><br><span class="line-number">304</span><br><span class="line-number">305</span><br><span class="line-number">306</span><br><span class="line-number">307</span><br><span class="line-number">308</span><br><span class="line-number">309</span><br><span class="line-number">310</span><br><span class="line-number">311</span><br><span class="line-number">312</span><br><span class="line-number">313</span><br><span class="line-number">314</span><br><span class="line-number">315</span><br><span class="line-number">316</span><br><span class="line-number">317</span><br><span class="line-number">318</span><br><span class="line-number">319</span><br><span class="line-number">320</span><br><span class="line-number">321</span><br><span class="line-number">322</span><br><span class="line-number">323</span><br><span class="line-number">324</span><br><span class="line-number">325</span><br><span class="line-number">326</span><br><span class="line-number">327</span><br><span class="line-number">328</span><br><span class="line-number">329</span><br><span class="line-number">330</span><br><span class="line-number">331</span><br><span class="line-number">332</span><br><span class="line-number">333</span><br><span class="line-number">334</span><br><span class="line-number">335</span><br><span class="line-number">336</span><br><span class="line-number">337</span><br><span class="line-number">338</span><br><span class="line-number">339</span><br><span class="line-number">340</span><br><span class="line-number">341</span><br><span class="line-number">342</span><br><span class="line-number">343</span><br><span class="line-number">344</span><br><span class="line-number">345</span><br><span class="line-number">346</span><br><span class="line-number">347</span><br><span class="line-number">348</span><br><span class="line-number">349</span><br><span class="line-number">350</span><br><span class="line-number">351</span><br><span class="line-number">352</span><br><span class="line-number">353</span><br><span class="line-number">354</span><br><span class="line-number">355</span><br><span class="line-number">356</span><br><span class="line-number">357</span><br><span class="line-number">358</span><br><span class="line-number">359</span><br><span class="line-number">360</span><br><span class="line-number">361</span><br><span class="line-number">362</span><br><span class="line-number">363</span><br><span class="line-number">364</span><br><span class="line-number">365</span><br><span class="line-number">366</span><br><span class="line-number">367</span><br><span class="line-number">368</span><br><span class="line-number">369</span><br><span class="line-number">370</span><br><span class="line-number">371</span><br><span class="line-number">372</span><br><span class="line-number">373</span><br><span class="line-number">374</span><br><span class="line-number">375</span><br><span class="line-number">376</span><br><span class="line-number">377</span><br><span class="line-number">378</span><br><span class="line-number">379</span><br><span class="line-number">380</span><br><span class="line-number">381</span><br><span class="line-number">382</span><br><span class="line-number">383</span><br><span class="line-number">384</span><br><span class="line-number">385</span><br><span class="line-number">386</span><br><span class="line-number">387</span><br><span class="line-number">388</span><br><span class="line-number">389</span><br><span class="line-number">390</span><br><span class="line-number">391</span><br><span class="line-number">392</span><br><span class="line-number">393</span><br><span class="line-number">394</span><br><span class="line-number">395</span><br><span class="line-number">396</span><br><span class="line-number">397</span><br><span class="line-number">398</span><br><span class="line-number">399</span><br><span class="line-number">400</span><br><span class="line-number">401</span><br><span class="line-number">402</span><br><span class="line-number">403</span><br><span class="line-number">404</span><br><span class="line-number">405</span><br><span class="line-number">406</span><br><span class="line-number">407</span><br><span class="line-number">408</span><br><span class="line-number">409</span><br><span class="line-number">410</span><br><span class="line-number">411</span><br><span class="line-number">412</span><br><span class="line-number">413</span><br><span class="line-number">414</span><br><span class="line-number">415</span><br><span class="line-number">416</span><br><span class="line-number">417</span><br><span class="line-number">418</span><br><span class="line-number">419</span><br><span class="line-number">420</span><br><span class="line-number">421</span><br><span class="line-number">422</span><br><span class="line-number">423</span><br><span class="line-number">424</span><br><span class="line-number">425</span><br><span class="line-number">426</span><br><span class="line-number">427</span><br><span class="line-number">428</span><br><span class="line-number">429</span><br><span class="line-number">430</span><br><span class="line-number">431</span><br><span class="line-number">432</span><br><span class="line-number">433</span><br><span class="line-number">434</span><br><span class="line-number">435</span><br><span class="line-number">436</span><br><span class="line-number">437</span><br><span class="line-number">438</span><br><span class="line-number">439</span><br><span class="line-number">440</span><br><span class="line-number">441</span><br><span class="line-number">442</span><br><span class="line-number">443</span><br><span class="line-number">444</span><br><span class="line-number">445</span><br><span class="line-number">446</span><br><span class="line-number">447</span><br><span class="line-number">448</span><br><span class="line-number">449</span><br><span class="line-number">450</span><br><span class="line-number">451</span><br><span class="line-number">452</span><br><span class="line-number">453</span><br><span class="line-number">454</span><br><span class="line-number">455</span><br><span class="line-number">456</span><br><span class="line-number">457</span><br><span class="line-number">458</span><br><span class="line-number">459</span><br><span class="line-number">460</span><br><span class="line-number">461</span><br><span class="line-number">462</span><br><span class="line-number">463</span><br><span class="line-number">464</span><br><span class="line-number">465</span><br><span class="line-number">466</span><br><span class="line-number">467</span><br><span class="line-number">468</span><br><span class="line-number">469</span><br><span class="line-number">470</span><br><span class="line-number">471</span><br><span class="line-number">472</span><br><span class="line-number">473</span><br><span class="line-number">474</span><br><span class="line-number">475</span><br><span class="line-number">476</span><br><span class="line-number">477</span><br><span class="line-number">478</span><br><span class="line-number">479</span><br><span class="line-number">480</span><br><span class="line-number">481</span><br><span class="line-number">482</span><br><span class="line-number">483</span><br><span class="line-number">484</span><br><span class="line-number">485</span><br><span class="line-number">486</span><br><span class="line-number">487</span><br><span class="line-number">488</span><br><span class="line-number">489</span><br><span class="line-number">490</span><br><span class="line-number">491</span><br><span class="line-number">492</span><br><span class="line-number">493</span><br><span class="line-number">494</span><br><span class="line-number">495</span><br><span class="line-number">496</span><br><span class="line-number">497</span><br><span class="line-number">498</span><br><span class="line-number">499</span><br><span class="line-number">500</span><br><span class="line-number">501</span><br><span class="line-number">502</span><br><span class="line-number">503</span><br><span class="line-number">504</span><br><span class="line-number">505</span><br><span class="line-number">506</span><br><span class="line-number">507</span><br><span class="line-number">508</span><br><span class="line-number">509</span><br><span class="line-number">510</span><br><span class="line-number">511</span><br><span class="line-number">512</span><br><span class="line-number">513</span><br><span class="line-number">514</span><br><span class="line-number">515</span><br><span class="line-number">516</span><br><span class="line-number">517</span><br><span class="line-number">518</span><br><span class="line-number">519</span><br><span class="line-number">520</span><br><span class="line-number">521</span><br><span class="line-number">522</span><br><span class="line-number">523</span><br><span class="line-number">524</span><br><span class="line-number">525</span><br><span class="line-number">526</span><br><span class="line-number">527</span><br><span class="line-number">528</span><br><span class="line-number">529</span><br><span class="line-number">530</span><br><span class="line-number">531</span><br><span class="line-number">532</span><br><span class="line-number">533</span><br><span class="line-number">534</span><br><span class="line-number">535</span><br><span class="line-number">536</span><br><span class="line-number">537</span><br><span class="line-number">538</span><br><span class="line-number">539</span><br><span class="line-number">540</span><br><span class="line-number">541</span><br><span class="line-number">542</span><br><span class="line-number">543</span><br><span class="line-number">544</span><br><span class="line-number">545</span><br><span class="line-number">546</span><br><span class="line-number">547</span><br><span class="line-number">548</span><br><span class="line-number">549</span><br><span class="line-number">550</span><br><span class="line-number">551</span><br><span class="line-number">552</span><br><span class="line-number">553</span><br><span class="line-number">554</span><br><span class="line-number">555</span><br><span class="line-number">556</span><br><span class="line-number">557</span><br><span class="line-number">558</span><br><span class="line-number">559</span><br><span class="line-number">560</span><br><span class="line-number">561</span><br><span class="line-number">562</span><br><span class="line-number">563</span><br><span class="line-number">564</span><br><span class="line-number">565</span><br><span class="line-number">566</span><br><span class="line-number">567</span><br><span class="line-number">568</span><br><span class="line-number">569</span><br><span class="line-number">570</span><br><span class="line-number">571</span><br><span class="line-number">572</span><br><span class="line-number">573</span><br><span class="line-number">574</span><br><span class="line-number">575</span><br><span class="line-number">576</span><br><span class="line-number">577</span><br><span class="line-number">578</span><br><span class="line-number">579</span><br><span class="line-number">580</span><br><span class="line-number">581</span><br><span class="line-number">582</span><br><span class="line-number">583</span><br><span class="line-number">584</span><br><span class="line-number">585</span><br><span class="line-number">586</span><br><span class="line-number">587</span><br><span class="line-number">588</span><br><span class="line-number">589</span><br><span class="line-number">590</span><br><span class="line-number">591</span><br><span class="line-number">592</span><br><span class="line-number">593</span><br><span class="line-number">594</span><br><span class="line-number">595</span><br><span class="line-number">596</span><br><span class="line-number">597</span><br><span class="line-number">598</span><br><span class="line-number">599</span><br><span class="line-number">600</span><br><span class="line-number">601</span><br><span class="line-number">602</span><br><span class="line-number">603</span><br><span class="line-number">604</span><br><span class="line-number">605</span><br><span class="line-number">606</span><br><span class="line-number">607</span><br><span class="line-number">608</span><br><span class="line-number">609</span><br><span class="line-number">610</span><br><span class="line-number">611</span><br><span class="line-number">612</span><br><span class="line-number">613</span><br><span class="line-number">614</span><br><span class="line-number">615</span><br><span class="line-number">616</span><br><span class="line-number">617</span><br><span class="line-number">618</span><br><span class="line-number">619</span><br><span class="line-number">620</span><br><span class="line-number">621</span><br><span class="line-number">622</span><br><span class="line-number">623</span><br><span class="line-number">624</span><br><span class="line-number">625</span><br><span class="line-number">626</span><br><span class="line-number">627</span><br><span class="line-number">628</span><br><span class="line-number">629</span><br><span class="line-number">630</span><br><span class="line-number">631</span><br><span class="line-number">632</span><br><span class="line-number">633</span><br><span class="line-number">634</span><br><span class="line-number">635</span><br><span class="line-number">636</span><br><span class="line-number">637</span><br><span class="line-number">638</span><br><span class="line-number">639</span><br><span class="line-number">640</span><br><span class="line-number">641</span><br><span class="line-number">642</span><br><span class="line-number">643</span><br><span class="line-number">644</span><br><span class="line-number">645</span><br><span class="line-number">646</span><br><span class="line-number">647</span><br><span class="line-number">648</span><br><span class="line-number">649</span><br><span class="line-number">650</span><br><span class="line-number">651</span><br><span class="line-number">652</span><br><span class="line-number">653</span><br><span class="line-number">654</span><br><span class="line-number">655</span><br><span class="line-number">656</span><br><span class="line-number">657</span><br><span class="line-number">658</span><br><span class="line-number">659</span><br><span class="line-number">660</span><br><span class="line-number">661</span><br><span class="line-number">662</span><br><span class="line-number">663</span><br><span class="line-number">664</span><br><span class="line-number">665</span><br><span class="line-number">666</span><br><span class="line-number">667</span><br><span class="line-number">668</span><br><span class="line-number">669</span><br><span class="line-number">670</span><br><span class="line-number">671</span><br><span class="line-number">672</span><br><span class="line-number">673</span><br><span class="line-number">674</span><br><span class="line-number">675</span><br><span class="line-number">676</span><br><span class="line-number">677</span><br><span class="line-number">678</span><br><span class="line-number">679</span><br><span class="line-number">680</span><br><span class="line-number">681</span><br><span class="line-number">682</span><br><span class="line-number">683</span><br><span class="line-number">684</span><br><span class="line-number">685</span><br><span class="line-number">686</span><br><span class="line-number">687</span><br><span class="line-number">688</span><br><span class="line-number">689</span><br><span class="line-number">690</span><br><span class="line-number">691</span><br><span class="line-number">692</span><br><span class="line-number">693</span><br><span class="line-number">694</span><br><span class="line-number">695</span><br><span class="line-number">696</span><br><span class="line-number">697</span><br><span class="line-number">698</span><br><span class="line-number">699</span><br><span class="line-number">700</span><br><span class="line-number">701</span><br><span class="line-number">702</span><br><span class="line-number">703</span><br><span class="line-number">704</span><br><span class="line-number">705</span><br><span class="line-number">706</span><br><span class="line-number">707</span><br><span class="line-number">708</span><br><span class="line-number">709</span><br><span class="line-number">710</span><br><span class="line-number">711</span><br><span class="line-number">712</span><br><span class="line-number">713</span><br><span class="line-number">714</span><br><span class="line-number">715</span><br><span class="line-number">716</span><br><span class="line-number">717</span><br><span class="line-number">718</span><br><span class="line-number">719</span><br><span class="line-number">720</span><br><span class="line-number">721</span><br><span class="line-number">722</span><br><span class="line-number">723</span><br><span class="line-number">724</span><br><span class="line-number">725</span><br><span class="line-number">726</span><br><span class="line-number">727</span><br><span class="line-number">728</span><br><span class="line-number">729</span><br><span class="line-number">730</span><br><span class="line-number">731</span><br><span class="line-number">732</span><br><span class="line-number">733</span><br><span class="line-number">734</span><br><span class="line-number">735</span><br><span class="line-number">736</span><br><span class="line-number">737</span><br><span class="line-number">738</span><br><span class="line-number">739</span><br><span class="line-number">740</span><br><span class="line-number">741</span><br><span class="line-number">742</span><br><span class="line-number">743</span><br><span class="line-number">744</span><br><span class="line-number">745</span><br><span class="line-number">746</span><br><span class="line-number">747</span><br><span class="line-number">748</span><br><span class="line-number">749</span><br><span class="line-number">750</span><br><span class="line-number">751</span><br><span class="line-number">752</span><br><span class="line-number">753</span><br><span class="line-number">754</span><br><span class="line-number">755</span><br><span class="line-number">756</span><br><span class="line-number">757</span><br><span class="line-number">758</span><br><span class="line-number">759</span><br><span class="line-number">760</span><br><span class="line-number">761</span><br><span class="line-number">762</span><br><span class="line-number">763</span><br><span class="line-number">764</span><br><span class="line-number">765</span><br><span class="line-number">766</span><br><span class="line-number">767</span><br><span class="line-number">768</span><br><span class="line-number">769</span><br><span class="line-number">770</span><br><span class="line-number">771</span><br><span class="line-number">772</span><br><span class="line-number">773</span><br><span class="line-number">774</span><br><span class="line-number">775</span><br><span class="line-number">776</span><br><span class="line-number">777</span><br><span class="line-number">778</span><br></div></div><h2 id="保持会话采用jwt" tabindex="-1"><a class="header-anchor" href="#保持会话采用jwt" aria-hidden="true">#</a> 保持会话采用JWT</h2>
<p>读取的配置包括：秘钥（采用JWT HMAC-SHA algorithm必须设置72个字符）和过期时间</p>
<p>方法：生成Token、判断Token是否有效、获取<a href="https://blog.csdn.net/fudaxing/article/details/53907763" target="_blank" rel="noopener noreferrer">Claims<ExternalLinkIcon/></a>(放入token中的额外参数Map形式保存)</p>
<div class="language-java ext-java line-numbers-mode"><pre v-pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">cn<span class="token punctuation">.</span>makerknz<span class="token punctuation">.</span>product<span class="token punctuation">.</span>server<span class="token punctuation">.</span>utils</span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token namespace">io<span class="token punctuation">.</span>jsonwebtoken<span class="token punctuation">.</span></span><span class="token operator">*</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">io<span class="token punctuation">.</span>jsonwebtoken<span class="token punctuation">.</span>security<span class="token punctuation">.</span></span><span class="token class-name">Keys</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">lombok<span class="token punctuation">.</span></span><span class="token class-name">Data</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">lombok<span class="token punctuation">.</span>extern<span class="token punctuation">.</span>slf4j<span class="token punctuation">.</span></span><span class="token class-name">Slf4j</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>beans<span class="token punctuation">.</span>factory<span class="token punctuation">.</span>annotation<span class="token punctuation">.</span></span><span class="token class-name">Value</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>boot<span class="token punctuation">.</span>context<span class="token punctuation">.</span>properties<span class="token punctuation">.</span></span><span class="token class-name">ConfigurationProperties</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>stereotype<span class="token punctuation">.</span></span><span class="token class-name">Component</span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token namespace">javax<span class="token punctuation">.</span>crypto<span class="token punctuation">.</span></span><span class="token class-name">SecretKey</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">Date</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">Map</span><span class="token punctuation">;</span>

<span class="token doc-comment comment">/**
 * @Author: maker_knz
 * @Date: 2021/5/31/031 16:49
 * @Version 1.0
 */</span>

<span class="token annotation punctuation">@Data</span>
<span class="token annotation punctuation">@ConfigurationProperties</span><span class="token punctuation">(</span>prefix <span class="token operator">=</span> <span class="token string">"jwt"</span><span class="token punctuation">)</span>
<span class="token annotation punctuation">@Component</span>
<span class="token annotation punctuation">@Slf4j</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">JwtTokenUtils</span> <span class="token punctuation">{</span>

    <span class="token doc-comment comment">/**
     * 秘钥
     * - 默认maker_knz
     */</span>
    <span class="token annotation punctuation">@Value</span><span class="token punctuation">(</span><span class="token string">"${secret:maker_knz}"</span><span class="token punctuation">)</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> secret<span class="token punctuation">;</span>

    <span class="token doc-comment comment">/**
     * 有效期，单位秒
     * - 默认2周
     */</span>
    <span class="token annotation punctuation">@Value</span><span class="token punctuation">(</span><span class="token string">"${expire-time-in-second:1209600}"</span><span class="token punctuation">)</span>
    <span class="token keyword">private</span> <span class="token class-name">Long</span> expirationTimeInSecond<span class="token punctuation">;</span>

    <span class="token doc-comment comment">/**
     * 从token中获取claim
     *
     * <span class="token keyword">@param</span> <span class="token parameter">token</span> token
     * <span class="token keyword">@return</span> claim
     */</span>
    <span class="token keyword">public</span> <span class="token class-name">Claims</span> <span class="token function">getClaimsFromToken</span><span class="token punctuation">(</span><span class="token class-name">String</span> token<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">try</span> <span class="token punctuation">{</span>
            <span class="token keyword">return</span> <span class="token class-name">Jwts</span><span class="token punctuation">.</span><span class="token function">parser</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
                    <span class="token punctuation">.</span><span class="token function">setSigningKey</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>secret<span class="token punctuation">.</span><span class="token function">getBytes</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                    <span class="token punctuation">.</span><span class="token function">parseClaimsJws</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span>
                    <span class="token punctuation">.</span><span class="token function">getBody</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">ExpiredJwtException</span> <span class="token operator">|</span> <span class="token class-name">UnsupportedJwtException</span> <span class="token operator">|</span> <span class="token class-name">MalformedJwtException</span> <span class="token operator">|</span> <span class="token class-name">IllegalArgumentException</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            log<span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span><span class="token string">"token解析错误"</span><span class="token punctuation">,</span> e<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IllegalArgumentException</span><span class="token punctuation">(</span><span class="token string">"Token invalided."</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    <span class="token doc-comment comment">/**
     * 获取token的过期时间
     *
     * <span class="token keyword">@param</span> <span class="token parameter">token</span> token
     * <span class="token keyword">@return</span> 过期时间
     */</span>
    <span class="token keyword">public</span> <span class="token class-name">Date</span> <span class="token function">getExpirationDateFromToken</span><span class="token punctuation">(</span><span class="token class-name">String</span> token<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token function">getClaimsFromToken</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">getExpiration</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token doc-comment comment">/**
     * 判断token是否过期
     *
     * <span class="token keyword">@param</span> <span class="token parameter">token</span> token
     * <span class="token keyword">@return</span> 已过期返回true，未过期返回false
     */</span>
    <span class="token keyword">private</span> <span class="token class-name">Boolean</span> <span class="token function">isTokenExpired</span><span class="token punctuation">(</span><span class="token class-name">String</span> token<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">Date</span> expiration <span class="token operator">=</span> <span class="token function">getExpirationDateFromToken</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> expiration<span class="token punctuation">.</span><span class="token function">before</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token doc-comment comment">/**
     * 计算token的过期时间
     *
     * <span class="token keyword">@return</span> 过期时间
     */</span>
    <span class="token keyword">public</span> <span class="token class-name">Date</span> <span class="token function">getExpirationTime</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token class-name">System</span><span class="token punctuation">.</span><span class="token function">currentTimeMillis</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token keyword">this</span><span class="token punctuation">.</span>expirationTimeInSecond <span class="token operator">*</span> <span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token doc-comment comment">/**
     * 为指定用户生成token
     *
     * <span class="token keyword">@param</span> <span class="token parameter">claims</span> 用户信息
     * <span class="token keyword">@return</span> token
     */</span>
    <span class="token keyword">public</span> <span class="token class-name">String</span> <span class="token function">generateToken</span><span class="token punctuation">(</span><span class="token class-name">Map</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">Object</span><span class="token punctuation">></span></span> claims<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">Date</span> createdTime <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">Date</span> expirationTime <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">getExpirationTime</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>


        <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> keyBytes <span class="token operator">=</span> secret<span class="token punctuation">.</span><span class="token function">getBytes</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">SecretKey</span> key <span class="token operator">=</span> <span class="token class-name">Keys</span><span class="token punctuation">.</span><span class="token function">hmacShaKeyFor</span><span class="token punctuation">(</span>keyBytes<span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token keyword">return</span> <span class="token class-name">Jwts</span><span class="token punctuation">.</span><span class="token function">builder</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">setClaims</span><span class="token punctuation">(</span>claims<span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">setIssuedAt</span><span class="token punctuation">(</span>createdTime<span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">setExpiration</span><span class="token punctuation">(</span>expirationTime<span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">signWith</span><span class="token punctuation">(</span>key<span class="token punctuation">,</span> <span class="token class-name">SignatureAlgorithm</span><span class="token punctuation">.</span>HS256<span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">compact</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token doc-comment comment">/**
     * 判断token是否非法
     *
     * <span class="token keyword">@param</span> <span class="token parameter">token</span> token
     * <span class="token keyword">@return</span> 未过期返回true，否则返回false
     */</span>
    <span class="token keyword">public</span> <span class="token class-name">Boolean</span> <span class="token function">validateToken</span><span class="token punctuation">(</span><span class="token class-name">String</span> token<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token operator">!</span><span class="token function">isTokenExpired</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br></div></div><h2 id="通过切面进行登录和权限认证" tabindex="-1"><a class="header-anchor" href="#通过切面进行登录和权限认证" aria-hidden="true">#</a> 通过切面进行登录和权限认证</h2>
<p>使用AOP进行切面，首先需要做两个注解用来做切面的入口。从请求头X-token中获取token的值，然后使用上面的JwtUtils工具获取token中的Claims，和判断是否过期。</p>
<p>访问权限的注解</p>
<div class="language-text ext-text line-numbers-mode"><pre v-pre class="language-text"><code>package cn.makerknz.product.server.annotation;

import java.lang.annotation.*;

/**
 * 检查是否有访问权限的注解，该注解仅可以使用在方法上
 * @Author: maker_knz
 * @Date: 2021/6/1/001 10:03
 * @Version 1.0
 */

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
public @interface CheckAuthorization {

    // 角色的名称
    String value();

}
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br></div></div><p>访问登录的注解CheckLogin</p>
<div class="language-java ext-java line-numbers-mode"><pre v-pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">cn<span class="token punctuation">.</span>makerknz<span class="token punctuation">.</span>product<span class="token punctuation">.</span>server<span class="token punctuation">.</span>annotation</span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token namespace">java<span class="token punctuation">.</span>lang<span class="token punctuation">.</span>annotation<span class="token punctuation">.</span></span><span class="token operator">*</span><span class="token punctuation">;</span>

<span class="token doc-comment comment">/**
 * 检查是否登录的注解
 * @Author: maker_knz
 * @Date: 2021/5/31/031 17:59
 * @Version 1.0
 */</span>

<span class="token annotation punctuation">@Documented</span>
<span class="token annotation punctuation">@Retention</span><span class="token punctuation">(</span><span class="token class-name">RetentionPolicy</span><span class="token punctuation">.</span>RUNTIME<span class="token punctuation">)</span>
<span class="token annotation punctuation">@Target</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token class-name">ElementType</span><span class="token punctuation">.</span>METHOD <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token annotation punctuation">@interface</span> <span class="token class-name">CheckLogin</span> <span class="token punctuation">{</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div><p>切面认证</p>
<div class="language-text ext-text line-numbers-mode"><pre v-pre class="language-text"><code>package cn.makerknz.product.server.auth;

import cn.makerknz.product.server.annotation.CheckAuthorization;
import cn.makerknz.product.server.utils.JwtTokenUtils;
import io.jsonwebtoken.Claims;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @Author: maker_knz
 * @Date: 2021/6/1/001 10:05
 * @Version 1.0
 */

@Aspect
@Component
public class AuthAspect {

    @Autowired
    private JwtTokenUtils jwtTokenUtils;

    Map&lt;String, Integer> roleMap = new HashMap&lt;>(3);
    
    /**
     * 根据之前数据库角色生成，默认
     */
    public AuthAspect() {
        roleMap.put("admin", 0);
        roleMap.put("private", 1);
        roleMap.put("company", 2);
    }

    /**
     * 切面检查权限问题
     * @param point
     * @return
     */
    @Around("@annotation(cn.makerknz.product.server.annotation.CheckAuthorization)")
    public Object checkAuth(ProceedingJoinPoint point) {
        try {
            // 1.验证token是否合法
            HttpServletRequest request = this.getHttpServletRequest();
            String token = this.getToken(request);
            // 2.验证角色是否匹配
            this.setUserInfo(request, token);
            Integer role = (Integer) request.getAttribute("role");
            MethodSignature signature = (MethodSignature) point.getSignature();
            Method method = signature.getMethod();
            CheckAuthorization annotation = method.getAnnotation(CheckAuthorization.class);
            String value = annotation.value();
            if (!Objects.equals(roleMap.get(value), role)) {
                throw new SecurityException("用户无权访问!");
            }
            return point.proceed();
        } catch (Throwable throwable) {
            throw new SecurityException("用户无权访问!", throwable);
        }
    }

    /**
     * 切面验证用户是否登录
     * @param point
     * @return
     */
    @Around("@annotation(cn.makerknz.product.server.annotation.CheckLogin)")
    public Object checkLogin(ProceedingJoinPoint point) {

        try {
            HttpServletRequest request = this.getHttpServletRequest();
            String token = this.getToken(request);
            // 如果检验成功将用户信息设置到request的atribute里面
            this.setUserInfo(request, token);

            return point.proceed();
        } catch (Throwable throwable) {
            throw new SecurityException("Token不合法");
        }
    }

    /**
     * 从请求头中获取HttpServletRequest
     * @return
     */
    private HttpServletRequest getHttpServletRequest() {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
        return servletRequestAttributes.getRequest();
    }

    /**
     * 从请求头中获取Token
     * @param request
     * @return
     */
    private String getToken(HttpServletRequest request) {
        // 1.从header中获取token
        String token = request.getHeader("X-token");
        // 2.校验token是否合法
        Boolean isValid = jwtTokenUtils.validateToken(token);
        if (!isValid) {
            throw new SecurityException("Token不合法");
        }
        return token;
    }

    /**
     * 在请求头中获取用户信息存储在claims中，这些信息是用来权限认证的基础
     * @param request
     * @param token
     */
    private void setUserInfo(HttpServletRequest request, String token) {
        Claims claims = jwtTokenUtils.getClaimsFromToken(token);
        request.setAttribute("id", claims.get("id"));
        request.setAttribute("nickname", claims.get("nickname"));
        request.setAttribute("role", claims.get("role"));
    }

}
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br></div></div><h2 id="用户注册、登录" tabindex="-1"><a class="header-anchor" href="#用户注册、登录" aria-hidden="true">#</a> 用户注册、登录</h2>
<h3 id="验证码" tabindex="-1"><a class="header-anchor" href="#验证码" aria-hidden="true">#</a> 验证码</h3>
<p>此处为模拟发送，可以自己买短信服务接入，获取验证码的次数通过Redis保存，并设置失效时间。</p>
<div class="language-text ext-text line-numbers-mode"><pre v-pre class="language-text"><code>package cn.makerknz.product.server.utils;

import cn.makerknz.product.server.domain.enums.SmsTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;

/**
 * @Author: maker_knz
 * @Date: 2021/7/12/012 10:14
 * @Version 1.0
 */

@Slf4j
@Component
public class SmsUtils {

    @Autowired
    private RedisTemplate&lt;Object, Object> redisTemplate;

    private static final Integer AVAILABLE_TIME = 5;

    private static final Integer CODE_LENGTH = 4;

    private final Integer SMS_LIMIT_COUNT = 3;

    public void send(String phoneNo, SmsTypeEnum smsType) {
        // 判断验证码是否存在
        Object value = redisTemplate.opsForValue().get(this.buildSmsCodeKey(phoneNo, smsType));
        if (value != null) {
            throw new RuntimeException("验证码发送中");
        }

        // 1. 生成验证码
        String code = this.generate();

        // 2.发送code
        log.info("手机{}的验证码为：code = {}", phoneNo, code);

        // 3.将code存储, 并设置发送的次数
        this.save(phoneNo, code, smsType);
        this.sendCountLimit(phoneNo, smsType);
    }


    /**
     * 验证验证码
     *
     * @param phoneNo
     * @param code
     * @param smsTypeEnum
     * @return SmsResponse
     */
    public boolean validateCode(String phoneNo, String code, SmsTypeEnum smsTypeEnum) {
        // 1、判断上次注册码是否已经失效
        String codeNum = this.get(phoneNo, smsTypeEnum);
        if (codeNum == null) {
            log.warn("[验证验证码], 验证码失效");
            throw new RuntimeException("验证码失效");
        }

        // 2、判断code是否相等
        if (!code.equals(codeNum)) {
            log.warn("[验证验证码], 验证码错误,验证码={},存储的验证码={},请求类型={}", code, codeNum, smsTypeEnum);
            throw new RuntimeException("验证码错误");
        }

        // 3、验证成功,将验证码移除
        this.remove(phoneNo, smsTypeEnum);

        // 4、移除对次数的限制
        String limitKey = this.buildSmsLimitKey(phoneNo, smsTypeEnum);
        redisTemplate.delete(limitKey);

        return true;
    }

    /**
     * 限制验证码发送的次数
     * @param phoneNo
     * @param smsTypeEnum
     */
    private void sendCountLimit(String phoneNo, SmsTypeEnum smsTypeEnum) {
        String limitKey = this.buildSmsLimitKey(phoneNo, smsTypeEnum);
        long count = redisTemplate.opsForValue().increment(limitKey, 1);
        if (count > SMS_LIMIT_COUNT) {
            log.warn("[发送验证],验证码发送太频繁");
            throw new RuntimeException("验证码发送太频繁");
        } else {
            // 验证码次数凌晨清除 // TODO 可以设置为两个小时
            Duration duration = Duration.between(LocalDateTime.now(), LocalDate.now().plusDays(1).atTime(0, 0, 0));
            redisTemplate.expire(limitKey, duration.toMinutes(), TimeUnit.MINUTES);
        }
    }

    public String generate() {
        String code = RandomStringUtils.randomNumeric(CODE_LENGTH);
        return code;
    }

    /**
     * 保存验证码
     *
     * @param code
     */
    public void save(String phoneNo, String code, SmsTypeEnum smsTypeEnum) {

        String codeKey = this.buildSmsCodeKey(phoneNo, smsTypeEnum);

        // 让redis中存储配置分钟
        redisTemplate.opsForValue().set(codeKey,
                code, AVAILABLE_TIME, TimeUnit.MINUTES);
    }

    /**
     * 获取验证码
     *
     * @return
     */
    public String get(String phoneNo, SmsTypeEnum smsTypeEnum) {
        Object value = redisTemplate.opsForValue().get(this.buildSmsCodeKey(phoneNo, smsTypeEnum));
        if (value == null) {
            return null;
        }
        return (String) value;
    }

    /**
     * 移除验证码
     *
     * @param phoneNo
     */
    public void remove(String phoneNo, SmsTypeEnum smsTypeEnum) {
        redisTemplate.delete(this.buildSmsCodeKey(phoneNo, smsTypeEnum));
    }

    /**
     * 创建SMS code 的 KEY
     * @param phoneNo
     * @param smsTypeEnum
     * @return
     */
    public String buildSmsCodeKey(String phoneNo, SmsTypeEnum smsTypeEnum) {
        return "SMS_CODE:" + phoneNo.toLowerCase() + ":" + smsTypeEnum.getValue();
    }

    /**
     * 创建限制发送Code的次数KEY
     * @param phoneNo
     * @param smsTypeEnum
     * @return
     */
    public String buildSmsLimitKey(String phoneNo, SmsTypeEnum smsTypeEnum) {
        return "SMS_LIMIT:" + phoneNo.toLowerCase() + ":" + smsTypeEnum.getValue();
    }

}
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br><span class="line-number">151</span><br><span class="line-number">152</span><br><span class="line-number">153</span><br><span class="line-number">154</span><br><span class="line-number">155</span><br><span class="line-number">156</span><br><span class="line-number">157</span><br><span class="line-number">158</span><br><span class="line-number">159</span><br><span class="line-number">160</span><br><span class="line-number">161</span><br><span class="line-number">162</span><br><span class="line-number">163</span><br><span class="line-number">164</span><br></div></div><h3 id="注册相关的服务函数" tabindex="-1"><a class="header-anchor" href="#注册相关的服务函数" aria-hidden="true">#</a> 注册相关的服务函数</h3>
<p>发送验证码、判断验证是否有效、判断验证码是否超过次数等。</p>
<div class="language-java ext-java line-numbers-mode"><pre v-pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">cn<span class="token punctuation">.</span>makerknz<span class="token punctuation">.</span>product<span class="token punctuation">.</span>server<span class="token punctuation">.</span>service<span class="token punctuation">.</span>impl</span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token namespace">cn<span class="token punctuation">.</span>makerknz<span class="token punctuation">.</span>product<span class="token punctuation">.</span>server<span class="token punctuation">.</span>domain<span class="token punctuation">.</span>enums<span class="token punctuation">.</span></span><span class="token class-name">SmsTypeEnum</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">cn<span class="token punctuation">.</span>makerknz<span class="token punctuation">.</span>product<span class="token punctuation">.</span>server<span class="token punctuation">.</span>domain<span class="token punctuation">.</span>form<span class="token punctuation">.</span></span><span class="token class-name">UserRegisterForm</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">cn<span class="token punctuation">.</span>makerknz<span class="token punctuation">.</span>product<span class="token punctuation">.</span>server<span class="token punctuation">.</span>domain<span class="token punctuation">.</span>vo<span class="token punctuation">.</span></span><span class="token class-name">UserInfoVO</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">cn<span class="token punctuation">.</span>makerknz<span class="token punctuation">.</span>product<span class="token punctuation">.</span>server<span class="token punctuation">.</span>entity<span class="token punctuation">.</span></span><span class="token class-name">User</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">cn<span class="token punctuation">.</span>makerknz<span class="token punctuation">.</span>product<span class="token punctuation">.</span>server<span class="token punctuation">.</span>service<span class="token punctuation">.</span></span><span class="token class-name">IUserOperatorService</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">cn<span class="token punctuation">.</span>makerknz<span class="token punctuation">.</span>product<span class="token punctuation">.</span>server<span class="token punctuation">.</span>service<span class="token punctuation">.</span></span><span class="token class-name">IUserService</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">cn<span class="token punctuation">.</span>makerknz<span class="token punctuation">.</span>product<span class="token punctuation">.</span>server<span class="token punctuation">.</span>utils<span class="token punctuation">.</span></span><span class="token class-name">BCrypt</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">cn<span class="token punctuation">.</span>makerknz<span class="token punctuation">.</span>product<span class="token punctuation">.</span>server<span class="token punctuation">.</span>utils<span class="token punctuation">.</span></span><span class="token class-name">SmsUtils</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">cn<span class="token punctuation">.</span>makerknz<span class="token punctuation">.</span>product<span class="token punctuation">.</span>server<span class="token punctuation">.</span>utils<span class="token punctuation">.</span></span><span class="token class-name">UserUtils</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">com<span class="token punctuation">.</span>baomidou<span class="token punctuation">.</span>mybatisplus<span class="token punctuation">.</span>core<span class="token punctuation">.</span>conditions<span class="token punctuation">.</span>query<span class="token punctuation">.</span></span><span class="token class-name">QueryWrapper</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">lombok<span class="token punctuation">.</span>extern<span class="token punctuation">.</span>slf4j<span class="token punctuation">.</span></span><span class="token class-name">Slf4j</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>beans<span class="token punctuation">.</span>factory<span class="token punctuation">.</span>annotation<span class="token punctuation">.</span></span><span class="token class-name">Autowired</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>stereotype<span class="token punctuation">.</span></span><span class="token class-name">Service</span><span class="token punctuation">;</span>

<span class="token doc-comment comment">/**
 * @Author: maker_knz
 * @Date: 2021/10/28/028 16:41
 * @Version 1.0
 */</span>

<span class="token annotation punctuation">@Service</span>
<span class="token annotation punctuation">@Slf4j</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">UserOperatorServiceImpl</span> <span class="token keyword">implements</span> <span class="token class-name">IUserOperatorService</span> <span class="token punctuation">{</span>

    <span class="token annotation punctuation">@Autowired</span>
    <span class="token keyword">private</span> <span class="token class-name">IUserService</span> userService<span class="token punctuation">;</span>

    <span class="token annotation punctuation">@Autowired</span>
    <span class="token keyword">private</span> <span class="token class-name">SmsUtils</span> smsUtils<span class="token punctuation">;</span>

    <span class="token doc-comment comment">/**
     * 发送手机验证码
     *
     * <span class="token keyword">@param</span> <span class="token parameter">phoneNo</span>
     */</span>
    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">registerSmsSend</span><span class="token punctuation">(</span><span class="token class-name">String</span> phoneNo<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token comment">// 1.检测手机号是否已经注册</span>
        <span class="token class-name">QueryWrapper</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">User</span><span class="token punctuation">></span></span> userQueryWrapper <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">QueryWrapper</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        userQueryWrapper<span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token string">"phone"</span><span class="token punctuation">,</span> phoneNo<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">User</span> userServiceOne <span class="token operator">=</span> userService<span class="token punctuation">.</span><span class="token function">getOne</span><span class="token punctuation">(</span>userQueryWrapper<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>userServiceOne <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            log<span class="token punctuation">.</span><span class="token function">warn</span><span class="token punctuation">(</span><span class="token string">"[注册发送验证码],手机号错误，手机号{}已经注册"</span><span class="token punctuation">,</span> phoneNo<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">RuntimeException</span><span class="token punctuation">(</span><span class="token string">"[注册发送验证码],手机号错误"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">smsSend</span><span class="token punctuation">(</span>phoneNo<span class="token punctuation">,</span> <span class="token class-name">SmsTypeEnum</span><span class="token punctuation">.</span>SMS_REGISTER_USER<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token doc-comment comment">/**
     * 修改密码发送手机验证码
     *
     * <span class="token keyword">@param</span> <span class="token parameter">phoneNo</span>
     */</span>
    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">changePasswordSmsSend</span><span class="token punctuation">(</span><span class="token class-name">String</span> phoneNo<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">smsSend</span><span class="token punctuation">(</span>phoneNo<span class="token punctuation">,</span> <span class="token class-name">SmsTypeEnum</span><span class="token punctuation">.</span>SMS_CHANGE_PASSWORD<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token doc-comment comment">/**
     * 第三方绑定时注册或绑定用户的验证码
     *
     * <span class="token keyword">@param</span> <span class="token parameter">phoneNo</span>
     */</span>
    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">registerOrBindSmsSend</span><span class="token punctuation">(</span><span class="token class-name">String</span> phoneNo<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">smsSend</span><span class="token punctuation">(</span>phoneNo<span class="token punctuation">,</span> <span class="token class-name">SmsTypeEnum</span><span class="token punctuation">.</span>SMS_SOCIAL_REGISTER_BIND<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token doc-comment comment">/**
     * 注册
     *
     * <span class="token keyword">@param</span> <span class="token parameter">registerForm</span>
     */</span>
    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> <span class="token class-name">UserInfoVO</span> <span class="token function">register</span><span class="token punctuation">(</span><span class="token class-name">UserRegisterForm</span> registerForm<span class="token punctuation">,</span> <span class="token class-name">SmsTypeEnum</span> type<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token comment">// 2.判断用户名&amp;&amp;手机号是否重复</span>
        <span class="token class-name">QueryWrapper</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">User</span><span class="token punctuation">></span></span> userQueryWrapper <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">QueryWrapper</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        userQueryWrapper<span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token string">"phone"</span><span class="token punctuation">,</span> registerForm<span class="token punctuation">.</span><span class="token function">getPhone</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">User</span> userServiceOne <span class="token operator">=</span> userService<span class="token punctuation">.</span><span class="token function">getOne</span><span class="token punctuation">(</span>userQueryWrapper<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>userServiceOne <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            log<span class="token punctuation">.</span><span class="token function">warn</span><span class="token punctuation">(</span><span class="token string">"[注册],用户名已经存在，用户名:{}"</span><span class="token punctuation">,</span> registerForm<span class="token punctuation">.</span><span class="token function">getPhone</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">RuntimeException</span><span class="token punctuation">(</span><span class="token string">"[注册],用户名已经存在"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token comment">// 3.判断验证码是否有效</span>
        <span class="token keyword">boolean</span> validateCode <span class="token operator">=</span> smsUtils<span class="token punctuation">.</span><span class="token function">validateCode</span><span class="token punctuation">(</span>registerForm<span class="token punctuation">.</span><span class="token function">getPhone</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> registerForm<span class="token punctuation">.</span><span class="token function">getCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> type<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>validateCode<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">RuntimeException</span><span class="token punctuation">(</span><span class="token string">"验证码错误"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token comment">// 4.生成nickname</span>
        <span class="token class-name">String</span> nickname <span class="token operator">=</span> <span class="token class-name">UserUtils</span><span class="token punctuation">.</span><span class="token function">autoCreateNickname</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token comment">// 4.将注册内容保存到数据库</span>
        <span class="token class-name">User</span> newUser <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">User</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        newUser<span class="token punctuation">.</span><span class="token function">setPhone</span><span class="token punctuation">(</span>registerForm<span class="token punctuation">.</span><span class="token function">getPhone</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        newUser<span class="token punctuation">.</span><span class="token function">setIcon</span><span class="token punctuation">(</span><span class="token string">"https://avatar.csdnimg.cn/9/0/0/1_maker_knz_1609583120.jpg"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        newUser<span class="token punctuation">.</span><span class="token function">setPassword</span><span class="token punctuation">(</span><span class="token class-name">BCrypt</span><span class="token punctuation">.</span><span class="token function">hashpw</span><span class="token punctuation">(</span>registerForm<span class="token punctuation">.</span><span class="token function">getPassword</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">BCrypt</span><span class="token punctuation">.</span><span class="token function">gensalt</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        newUser<span class="token punctuation">.</span><span class="token function">setUsername</span><span class="token punctuation">(</span>nickname<span class="token punctuation">)</span><span class="token punctuation">;</span>
        newUser<span class="token punctuation">.</span><span class="token function">setRole</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token comment">// 7.保存</span>
        <span class="token keyword">boolean</span> save <span class="token operator">=</span> userService<span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span>newUser<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>save<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">RuntimeException</span><span class="token punctuation">(</span><span class="token string">"保存失败"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token class-name">UserInfoVO</span> userInfoVO <span class="token operator">=</span> <span class="token class-name">UserInfoVO</span><span class="token punctuation">.</span><span class="token function">builder</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">id</span><span class="token punctuation">(</span>newUser<span class="token punctuation">.</span><span class="token function">getId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">role</span><span class="token punctuation">(</span>newUser<span class="token punctuation">.</span><span class="token function">getRole</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">trueName</span><span class="token punctuation">(</span>newUser<span class="token punctuation">.</span><span class="token function">getTruename</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">username</span><span class="token punctuation">(</span>newUser<span class="token punctuation">.</span><span class="token function">getUsername</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token comment">// 8.返回个人信息</span>
        <span class="token keyword">return</span> userInfoVO<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token doc-comment comment">/**
     * 修改用户密码
     *
     * <span class="token keyword">@param</span> <span class="token parameter">registerForm</span>
     * <span class="token keyword">@return</span>
     */</span>
    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> <span class="token class-name">UserInfoVO</span> <span class="token function">changeUserPassword</span><span class="token punctuation">(</span><span class="token class-name">UserRegisterForm</span> registerForm<span class="token punctuation">)</span> <span class="token punctuation">{</span>

        <span class="token keyword">if</span> <span class="token punctuation">(</span>registerForm<span class="token punctuation">.</span><span class="token function">getPassword</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">isEmpty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            log<span class="token punctuation">.</span><span class="token function">warn</span><span class="token punctuation">(</span><span class="token string">"[修改密码],密码不能为空，用户名:{}"</span><span class="token punctuation">,</span> registerForm<span class="token punctuation">.</span><span class="token function">getPhone</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">RuntimeException</span><span class="token punctuation">(</span><span class="token string">"密码不能为空"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token comment">// 2.能过phone读取用户</span>
        <span class="token class-name">QueryWrapper</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">User</span><span class="token punctuation">></span></span> userQueryWrapper <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">QueryWrapper</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        userQueryWrapper<span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token string">"phone"</span><span class="token punctuation">,</span> registerForm<span class="token punctuation">.</span><span class="token function">getPhone</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">User</span> userServiceOne <span class="token operator">=</span> userService<span class="token punctuation">.</span><span class="token function">getOne</span><span class="token punctuation">(</span>userQueryWrapper<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>userServiceOne <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            log<span class="token punctuation">.</span><span class="token function">warn</span><span class="token punctuation">(</span><span class="token string">"[修改密码],用户不存在，用户名:{}"</span><span class="token punctuation">,</span> registerForm<span class="token punctuation">.</span><span class="token function">getPhone</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">RuntimeException</span><span class="token punctuation">(</span><span class="token string">"用户不存在"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token comment">// 3.判断验证码是否有效</span>
        <span class="token class-name">Boolean</span> validateCode <span class="token operator">=</span> smsUtils<span class="token punctuation">.</span><span class="token function">validateCode</span><span class="token punctuation">(</span>registerForm<span class="token punctuation">.</span><span class="token function">getPhone</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> registerForm<span class="token punctuation">.</span><span class="token function">getCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">SmsTypeEnum</span><span class="token punctuation">.</span>SMS_CHANGE_PASSWORD<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>validateCode<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            log<span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span><span class="token string">"[注册验证验证码], 验证验证码错误, 手机号 = {}, 验证码 = {}"</span><span class="token punctuation">,</span> registerForm<span class="token punctuation">.</span><span class="token function">getPhone</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> registerForm<span class="token punctuation">.</span><span class="token function">getCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">RuntimeException</span><span class="token punctuation">(</span><span class="token string">"验证验证码错误"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token comment">// 4.修改密码,加密存储</span>
        userServiceOne<span class="token punctuation">.</span><span class="token function">setPassword</span><span class="token punctuation">(</span><span class="token class-name">BCrypt</span><span class="token punctuation">.</span><span class="token function">hashpw</span><span class="token punctuation">(</span>registerForm<span class="token punctuation">.</span><span class="token function">getPassword</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">BCrypt</span><span class="token punctuation">.</span><span class="token function">gensalt</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token comment">// 7.保存</span>
        <span class="token keyword">boolean</span> update <span class="token operator">=</span> userService<span class="token punctuation">.</span><span class="token function">updateById</span><span class="token punctuation">(</span>userServiceOne<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>update<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            log<span class="token punctuation">.</span><span class="token function">warn</span><span class="token punctuation">(</span><span class="token string">"[修改密码],更新密码失败，用户名:{}"</span><span class="token punctuation">,</span> registerForm<span class="token punctuation">.</span><span class="token function">getPhone</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">RuntimeException</span><span class="token punctuation">(</span><span class="token string">"更新密码失败"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token class-name">UserInfoVO</span> userInfoVO <span class="token operator">=</span> <span class="token class-name">UserInfoVO</span><span class="token punctuation">.</span><span class="token function">builder</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">id</span><span class="token punctuation">(</span>userServiceOne<span class="token punctuation">.</span><span class="token function">getId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">role</span><span class="token punctuation">(</span>userServiceOne<span class="token punctuation">.</span><span class="token function">getRole</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">trueName</span><span class="token punctuation">(</span>userServiceOne<span class="token punctuation">.</span><span class="token function">getTruename</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">username</span><span class="token punctuation">(</span>userServiceOne<span class="token punctuation">.</span><span class="token function">getUsername</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token keyword">return</span> userInfoVO<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>


    <span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">smsSend</span><span class="token punctuation">(</span><span class="token class-name">String</span> phoneNo<span class="token punctuation">,</span> <span class="token class-name">SmsTypeEnum</span> smsType<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        smsUtils<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>phoneNo<span class="token punctuation">,</span> smsType<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br><span class="line-number">151</span><br><span class="line-number">152</span><br><span class="line-number">153</span><br><span class="line-number">154</span><br><span class="line-number">155</span><br><span class="line-number">156</span><br><span class="line-number">157</span><br><span class="line-number">158</span><br><span class="line-number">159</span><br><span class="line-number">160</span><br><span class="line-number">161</span><br><span class="line-number">162</span><br><span class="line-number">163</span><br><span class="line-number">164</span><br><span class="line-number">165</span><br><span class="line-number">166</span><br><span class="line-number">167</span><br><span class="line-number">168</span><br><span class="line-number">169</span><br><span class="line-number">170</span><br><span class="line-number">171</span><br><span class="line-number">172</span><br><span class="line-number">173</span><br><span class="line-number">174</span><br><span class="line-number">175</span><br><span class="line-number">176</span><br></div></div><h3 id="编写对外的接口" tabindex="-1"><a class="header-anchor" href="#编写对外的接口" aria-hidden="true">#</a> 编写对外的接口</h3>
<div class="language-text ext-text line-numbers-mode"><pre v-pre class="language-text"><code>package cn.makerknz.product.server.controller;


import cn.makerknz.product.server.annotation.CheckAuthorization;
import cn.makerknz.product.server.annotation.CheckLogin;
import cn.makerknz.product.server.domain.dto.JwtTokenRespDTO;
import cn.makerknz.product.server.domain.dto.LoginRespDTO;
import cn.makerknz.product.server.domain.dto.UserLoginDTO;
import cn.makerknz.product.server.domain.dto.UserRespDTO;
import cn.makerknz.product.server.domain.form.UserForm;
import cn.makerknz.product.server.domain.form.UserRegisterForm;
import cn.makerknz.product.server.domain.vo.ResultVO;
import cn.makerknz.product.server.domain.vo.UserInfoVO;
import cn.makerknz.product.server.domain.vo.UserVO;
import cn.makerknz.product.server.entity.User;
import cn.makerknz.product.server.domain.enums.ResponseEnum;
import cn.makerknz.product.server.domain.enums.SmsTypeEnum;
import cn.makerknz.product.server.service.IUserOperatorService;
import cn.makerknz.product.server.service.IUserService;
import cn.makerknz.product.server.utils.BCrypt;
import cn.makerknz.product.server.utils.JwtTokenUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * &lt;p>
 *  前端控制器
 * &lt;/p>
 *
 * @author maker knz
 * @since 2021-10-27
 */

@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {

    @Autowired
    private IUserService userService;

    @Autowired
    private JwtTokenUtils jwtTokenUtils;

    @Autowired
    private IUserOperatorService userOperatorService;

    @PostMapping("/login")
    public ResultVO login(@RequestBody UserLoginDTO userLoginDTO) {

        User user = new User();
        user.setPhone(userLoginDTO.getPhone());
        QueryWrapper&lt;User> queryWrapper = new QueryWrapper&lt;>(user);
        User one = userService.getOne(queryWrapper);
        if (one == null) {
            throw new RuntimeException();
        }
        boolean checkpw = BCrypt.checkpw(userLoginDTO.getPassword(), one.getPassword());
        if (!checkpw) {
            throw new RuntimeException();
        }

        // 发放token
        return ResultVO.success(this.genToken(one));
    }

    @GetMapping("/logout")
    public ResultVO login() {
        return ResultVO.success();
    }

    @GetMapping("/user-info")
    @CheckLogin
    public ResultVO&lt;UserInfoVO> userInfo(HttpServletRequest httpServletRequest) {
        UserInfoVO userInfoVO = UserInfoVO.builder()
                .id((Integer) httpServletRequest.getAttribute("id"))
                .username((String) httpServletRequest.getAttribute("nickname"))
                .trueName((String) httpServletRequest.getAttribute("nickname"))
                .build();
        return ResultVO.success(userInfoVO);
    }

    @GetMapping(path = "/{id}")
    @CheckLogin
    public User getUser(@PathVariable("id") Integer userId) {
        User user = userService.getById(userId);
        UserVO userVO = new UserVO();
        return user;
    }

    @PutMapping("/{id}")
    @CheckAuthorization("admin")
    public ResultVO updateUser(@PathVariable("id") Integer id, @RequestBody UserForm userForm) {
        User user = new User();
        BeanUtils.copyProperties(userForm, user);
        user.setId(id);
        boolean bUpdateUser = userService.updateById(user);
        if (!bUpdateUser) {
            return ResultVO.error(ResponseEnum.UPDATE_USER_ERROR);
        }

        return ResultVO.successMsg("修改用户成功");
    }

    @PostMapping("/add-user")
    @CheckAuthorization("admin")
    public ResultVO addUser(@RequestBody UserForm userForm) {
        User user = new User();
        BeanUtils.copyProperties(userForm, user);
        String hashpw = BCrypt.hashpw(userForm.getPassword(), BCrypt.gensalt());
        user.setPassword(hashpw);

        boolean save = userService.save(user);
        if (!save) {
            return ResultVO.error(ResponseEnum.ADD_USER_ERROR);
        }
        QueryWrapper&lt;User> queryWrapper = new QueryWrapper&lt;>(user);
        User one = userService.getOne(queryWrapper);

        return ResultVO.successMsg("添加用户成功");
    }

    @DeleteMapping("/delete-user/{id}")
    public ResultVO deleteUser(@PathVariable("id") Integer id) {
        boolean isDelete = this.userService.removeById(id);
        if (!isDelete) {
            throw new RuntimeException();
        }
        return ResultVO.success();
    }

    @GetMapping("/watiers")
    @CheckAuthorization("admin")
    public ResultVO getWatiers() {
        QueryWrapper&lt;User> userQueryWrapper = new QueryWrapper&lt;>();
        userQueryWrapper.eq("role", 2);
        List&lt;User> userList = this.userService.list(userQueryWrapper);
        return ResultVO.success(userList);
    }

    @GetMapping("/gen-token")
    public String genToken() {
        // 发放token
        Map&lt;String, Object> userInfo = new HashMap&lt;>(3);
        userInfo.put("id", 1);
        userInfo.put("nickname", "knz");
        userInfo.put("role", 0);
        String token = jwtTokenUtils.generateToken(userInfo);
        log.info("用户生成的token: {}", token);

        return token;
    }

    @GetMapping("/test")
    @CheckLogin
    public String test() {
        // 发放token
        log.info("成功获取");
        return "";
    }

    private LoginRespDTO genToken(User user) {
        // 发放token
        Map&lt;String, Object> userInfo = new HashMap&lt;>(3);
        userInfo.put("id", user.getId());
        userInfo.put("nickname", user.getUsername());
        userInfo.put("role", user.getRole());
        String token = jwtTokenUtils.generateToken(userInfo);
        log.info("用户生成的token: {}", token);
        LoginRespDTO loginRespDTO = LoginRespDTO.builder()
                .user(UserRespDTO.builder().id(user.getId()).wxNickname(user.getUsername()).build())
                .token(JwtTokenRespDTO.builder().token(token).expirationTime(jwtTokenUtils.getExpirationTime().getTime()).build())
                .build();

        return loginRespDTO;
    }

    @PostMapping("/register")
    public ResultVO registerUser(@RequestBody @Valid UserRegisterForm userForm, BindingResult result) {
        if(result.hasErrors()){
            for (ObjectError error : result.getAllErrors()) {
                throw new RuntimeException(error.getDefaultMessage());
            }
        }

        UserInfoVO register = this.userOperatorService.register(userForm, SmsTypeEnum.SMS_REGISTER_USER);

        return ResultVO.success(register);
    }

    @PostMapping("/change-password")
    public ResultVO changePassword(@RequestBody UserRegisterForm userForm) {

        UserInfoVO register = this.userOperatorService.changeUserPassword(userForm);

        return ResultVO.success(register);
    }

    @PostMapping("/register/code")
    public ResultVO registerCode(@RequestBody UserRegisterForm userForm) {
        userOperatorService.registerSmsSend(userForm.getPhone());
        return ResultVO.successMsg("发送验证码成功");
    }

    @PostMapping("/change-password/code")
    public ResultVO changePasswordCode(@RequestBody UserRegisterForm userForm) {
        userOperatorService.changeUserPassword(userForm);
        return ResultVO.successMsg("发送验证码成功");
    }

}
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br><span class="line-number">151</span><br><span class="line-number">152</span><br><span class="line-number">153</span><br><span class="line-number">154</span><br><span class="line-number">155</span><br><span class="line-number">156</span><br><span class="line-number">157</span><br><span class="line-number">158</span><br><span class="line-number">159</span><br><span class="line-number">160</span><br><span class="line-number">161</span><br><span class="line-number">162</span><br><span class="line-number">163</span><br><span class="line-number">164</span><br><span class="line-number">165</span><br><span class="line-number">166</span><br><span class="line-number">167</span><br><span class="line-number">168</span><br><span class="line-number">169</span><br><span class="line-number">170</span><br><span class="line-number">171</span><br><span class="line-number">172</span><br><span class="line-number">173</span><br><span class="line-number">174</span><br><span class="line-number">175</span><br><span class="line-number">176</span><br><span class="line-number">177</span><br><span class="line-number">178</span><br><span class="line-number">179</span><br><span class="line-number">180</span><br><span class="line-number">181</span><br><span class="line-number">182</span><br><span class="line-number">183</span><br><span class="line-number">184</span><br><span class="line-number">185</span><br><span class="line-number">186</span><br><span class="line-number">187</span><br><span class="line-number">188</span><br><span class="line-number">189</span><br><span class="line-number">190</span><br><span class="line-number">191</span><br><span class="line-number">192</span><br><span class="line-number">193</span><br><span class="line-number">194</span><br><span class="line-number">195</span><br><span class="line-number">196</span><br><span class="line-number">197</span><br><span class="line-number">198</span><br><span class="line-number">199</span><br><span class="line-number">200</span><br><span class="line-number">201</span><br><span class="line-number">202</span><br><span class="line-number">203</span><br><span class="line-number">204</span><br><span class="line-number">205</span><br><span class="line-number">206</span><br><span class="line-number">207</span><br><span class="line-number">208</span><br><span class="line-number">209</span><br><span class="line-number">210</span><br><span class="line-number">211</span><br><span class="line-number">212</span><br><span class="line-number">213</span><br><span class="line-number">214</span><br><span class="line-number">215</span><br><span class="line-number">216</span><br><span class="line-number">217</span><br><span class="line-number">218</span><br><span class="line-number">219</span><br><span class="line-number">220</span><br><span class="line-number">221</span><br><span class="line-number">222</span><br></div></div><h2 id="测试" tabindex="-1"><a class="header-anchor" href="#测试" aria-hidden="true">#</a> 测试</h2>
<h3 id="验证码测试" tabindex="-1"><a class="header-anchor" href="#验证码测试" aria-hidden="true">#</a> 验证码测试</h3>
<p>http://localhost:8080/user/register/code</p>
<div class="language-text ext-text line-numbers-mode"><pre v-pre class="language-text"><code>{
  "phone": "12345678901"
}
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p><img src="http://note.makerknz.cn/image-20211029180243893.png" alt="image-20211029180243893"></p>
<h3 id="注册" tabindex="-1"><a class="header-anchor" href="#注册" aria-hidden="true">#</a> 注册</h3>
<div class="language-text ext-text line-numbers-mode"><pre v-pre class="language-text"><code>{
  "truename": "maker_knz",
  "phone": "12345678901",
  "password": "123456",
  "code": "0592"
}
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p><img src="http://note.makerknz.cn/image-20211029180519305.png" alt="image-20211029180519305"></p>
<p><img src="http://note.makerknz.cn/image-20211029180539150.png" alt="image-20211029180539150"></p>
<h3 id="登录" tabindex="-1"><a class="header-anchor" href="#登录" aria-hidden="true">#</a> 登录</h3>
<div class="language-text ext-text line-numbers-mode"><pre v-pre class="language-text"><code>{
  "password": "123456",
  "phone": "12345678901"
}
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><p><img src="http://note.makerknz.cn/image-20211029180731194.png" alt="image-20211029180731194"></p>
<h3 id="获取用户信息" tabindex="-1"><a class="header-anchor" href="#获取用户信息" aria-hidden="true">#</a> 获取用户信息</h3>
<p>在Header中添加X-token</p>
<p><img src="http://note.makerknz.cn/image-20211103145628089.png" alt="image-20211103145628089"></p>
<p>获取成功返回的结果</p>
<div class="language-text ext-text line-numbers-mode"><pre v-pre class="language-text"><code>{
  "code": 2000,
  "data": {
    "id": 3,
    "username": "maker_46484810",
    "trueName": "maker_46484810"
  }
}
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><h3 id="鉴权" tabindex="-1"><a class="header-anchor" href="#鉴权" aria-hidden="true">#</a> 鉴权</h3>
<p>可以自己测试</p>
<h2 id="项目地址" tabindex="-1"><a class="header-anchor" href="#项目地址" aria-hidden="true">#</a> 项目地址</h2>
<p><a href="https://gitee.com/eaooglePlatform_he_jiaqi/product-manager-server/tree/%E6%B3%A8%E5%86%8C%E3%80%81%E7%99%BB%E5%BD%95%E5%92%8C%E9%89%B4%E6%9D%83" target="_blank" rel="noopener noreferrer">gitee<ExternalLinkIcon/></a></p>
<p>github:</p>
<h2 id="总结" tabindex="-1"><a class="header-anchor" href="#总结" aria-hidden="true">#</a> 总结</h2>
<p>此处的用户注册、登录和鉴权是一个通用的鉴权过程，如果不想使用shrio、spring security框架的同学可以参考。</p>
</template>
